直接 new error() 不够用,因其缺乏语义化类型标识,需手动设置 name 属性(如 err.name = 'autherror')并在 throw 前完成,避免压缩器移除;推荐用 err.name === 'xxx' 判断类型,而非 instanceof。

为什么直接 new Error() 不够用
业务代码里抛错时,如果全用 new Error(),捕获后只能靠 message 字符串匹配来区分错误类型——脆弱、易错、难维护。比如「用户未登录」和「权限不足」都可能返回相似的 message,但后续处理逻辑完全不同。这时候需要靠 name 属性做语义化标识,让错误本身携带类型信息。
如何正确设置 name 属性而不被覆盖
Error 构造函数本身不接受 name 作为参数,直接赋值 err.name = 'AuthError' 是可行的,但必须在 throw 前完成;否则 V8 或某些打包工具(如 Webpack + terser)在压缩时可能移除未被读取的属性,导致 name 退化为默认的 'Error'。
- ✅ 推荐写法:手动赋值 + 立即抛出
const err = new Error('Token expired');
err.name = 'AuthError';
throw err;
throw Object.assign(new Error('Token expired'), { name: 'AuthError' }); // 可能被压缩器误删
name,例如 (err as any).name 或定义 interface AuthError extends Error { name: 'AuthError' }
配合 instanceof 实现类型判断的局限性
很多人想用 instanceof 区分错误类型,但原生 Error 的子类(如 class AuthError extends Error)在跨 iframe 或不同 Error 构造函数环境(如微前端)中会失效——因为 instanceof 依赖原型链,而不同上下文的 Error 是不同构造函数。
- ✅ 更可靠的方式是检查
err.name === 'AuthError' - ✅ 可封装统一判断函数:
isAuthError(err: unknown): err is AuthError { return err instanceof Error && err.name === 'AuthError'; } - ⚠️ 注意:
name值建议全大写或 PascalCase(如'NetworkTimeout'),避免空格或特殊字符,防止 JSON 序列化或日志采集时出问题
在实际请求拦截中怎么用才不漏掉错误
Axios 或 Fetch 的错误处理常只关注 HTTP 状态码,忽略业务响应体里的错误码。这时应在响应解析阶段主动抛出自定义错误,把服务端返回的 code 映射为前端 name。
- 示例(Axios 响应拦截器):
axios.interceptors.response.use(
res => res,
err => {
if (err.response?.data?.code === 'AUTH_TOKEN_EXPIRED') {
const e = new Error('Access token expired');
e.name = 'AuthError';
throw e;
}
if (err.response?.data?.code === 'FORBIDDEN_ACTION') {
const e = new Error('Insufficient permissions');
e.name = 'PermissionError';
throw e;
}
throw err;
}
);
err.name 和 err.message,避免只传 err.toString() 丢失类型信息name 标识。真正容易被忽略的是压缩构建对属性赋值的干扰,以及服务端错误码与前端 name 的映射一致性。










