症状
遇到“TypeScript TS18046 — 错误类型为 unknown”时靠猜测只会浪费时间。请按证据排查:先复现症状,再执行针对性诊断,定位根因后修复,并用明确检查验证结果。
可观察到的症状包括:
- error TS18046: ‘e’ is of type unknown
- 启用严格模式后开始报错
- 在 catch 块中访问 e.message 无法编译
诊断
先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。
步骤 1
npx tsc --noEmit 2>&1 | grep TS18046
消息指出变量与操作,显示需要收窄的位置。
步骤 2
if (e instanceof Error) console.log(e.message);
instanceof Error 把 unknown 收窄为 Error,使 message 与 stack 可用。
常见诱因(按出现频率排序):
- 严格模式或 useUnknownInCatchVariables 使 catch 绑定为 unknown
- noUncheckedIndexedAccess 下索引访问返回 unknown
- JSON.parse 或泛型 API 返回 unknown,未收窄即使用
根因
启用 useUnknownInCatchVariables(strict 隐含)后,catch 子句绑定为 unknown,因为任何值都可能被抛出。在守卫证明更窄类型前,TypeScript 禁止访问 unknown 的成员。
修复
使用前先收窄:对错误类值用 instanceof Error,对结构用自定义 isApiError 守卫,并用辅助函数把 unknown 安全转换为消息。
注意:用 as Error 跳过检查会重新引入严格模式所要预防的运行期缺陷。
function messageOf(e: unknown): string {
if (e instanceof Error) return e.message;
if (typeof e === 'string') return e;
try { return JSON.stringify(e); } catch { return String(e); }
}
try { risky(); } catch (e: unknown) {
console.error(messageOf(e));
}
验证
运行 tsc –noEmit 并确认 TS18046 消失;补充分别抛出字符串与 Error 的测试,断言二者都产生可读消息。
修复后补充一条回归测试,复现原始症状,防止问题再次出现。
这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。