typescript 中 catch 的错误默认为 unknown 类型,需用类型守卫(如 iserror)收窄才能访问 message;推荐启用 useunknownincatchvariables 配置,并抛出自定义错误类以保障类型安全与可扩展性。

直接用 catch 捕获的错误默认是 unknown,TypeScript 不允许你直接访问 message 或 stack——这是保护机制,不是限制。关键在于主动收窄类型,而不是绕过检查。
启用 useUnknownInCatchVariables
这是 TypeScript 4.4+ 的推荐配置,强制 catch 参数为 unknown 类型,杜绝 any 隐式降级。在 tsconfig.json 中开启:
"useUnknownInCatchVariables": true- 搭配
"strict": true和"noImplicitAny": true效果更完整
开启后,下面代码会报错:
try { ... } catch (err) { console.log(err.message); } // ❌ err 是 unknown,不能访问 message
用类型守卫精准识别错误
不依赖 instanceof Error(它不能保证有 message),而用自定义类型守卫函数确认结构:
function isError(e: unknown): e is Error {
return e instanceof Error;
}
try {
await fetch('/api/data');
} catch (err) {
if (isError(err)) {
console.error('网络错误:', err.message);
} else {
console.error('未知错误:', err);
}
}
这样既安全又可扩展,后续还可补充 isAxiosError、isValidationError 等守卫。
统一业务错误结构,避免裸 throw
别直接 throw new Error('xxx'),而是抛出自定义错误类,让错误本身带类型语义:
class ApiError extends Error {
constructor(
public code: string,
public status: number,
public details?: Record<string unknown>
) {
super(`API ${code}: ${status}`);
this.name = 'ApiError';
}
}
// 在 fetch 封装中
async function apiGet<t>(url: string): Promise<t> {
const res = await fetch(url);
if (!res.ok) {
throw new ApiError('FETCH_FAILED', res.status, { url });
}
return res.json();
}
</t></t></string>
调用时,catch 中可直接按 ApiError 类型处理:
try {
const data = await apiGet<user>('/user/123');
} catch (err) {
if (err instanceof ApiError) {
// ✅ TypeScript 知道 err 有 code、status、details
if (err.code === 'FETCH_FAILED' && err.status === 401) {
redirectToLogin();
}
}
}</user>
异步链路中保持错误类型可推导
Promise 链或 async/await 中,错误不会自动带上泛型信息。要确保类型延续,可显式标注 catch 分支返回值:
- 用
Promise.catch()时,返回同类型 Promise,避免中断链路 - 在
async函数中,catch后可返回Promise.reject(new ApiError(...))继续传播结构化错误 - 避免在
catch中只写console.error就结束——这会让上层失去错误上下文
例如:
async function loadProfile(id: string): Promise<profile> {
try {
return await apiGet<profile>(`/profiles/${id}`);
} catch (err) {
if (err instanceof ApiError) {
throw new ProfileLoadError(err.code, err.details);
}
throw new ProfileLoadError('UNKNOWN_ERROR');
}
}</profile></profile>
这样下游能继续基于 ProfileLoadError 做分类处理,类型始终在线。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











