← 中文资源

简体中文版本

TypeScript TS18046 — 错误类型为 unknown

通过类型守卫收窄 unknown 值、使用 instanceof Error,并有意识地选择 useUnknownInCatchVariables,修复 TS18046。

阅读英文原文

症状

遇到“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 的测试,断言二者都产生可读消息。

修复后补充一条回归测试,复现原始症状,防止问题再次出现。

这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。