报错消失了,数据就可信吗?

接口返回 { "seats": "many" },代码却把它当成座位数量。加上 any 或断言后, 编辑器安静了,后续计算仍可能出错。类型检查通过,不能证明外部输入符合预期。

先预测:把响应断言成 { seats: number },会把字符串变成数字吗? 不会。断言只改变编译器看待它的方式。本页要在边界检查数据,再保留已确认的信息。

外部数据先验证再收窄 / Treat external data as unknown and validate it before trusting its type.外部数据先验证再收窄 / Treat external data as unknown and validate it before trusting its type.
外部数据先验证再收窄。

用检查把 unknown 收窄

unknown 表示尚不知道值是什么。读取属性和做计算之前,先检查存在性、 形状与字段条件。下面只接受非负整数座位数;不合法输入明确报错,避免进入业务计算。

ts
function readSeats(value: unknown): number {
  if (typeof value !== "object" || value === null) {
    throw new Error("Expected an object");
  }
  if (!("seats" in value)) {
    throw new Error("Missing seats");
  }
  const seats = value.seats;
  if (typeof seats !== "number" ||
      !Number.isInteger(seats) || seats < 0) {
    throw new Error("Invalid seat count");
  }
  return seats;
}

检查只证明写明的条件。这里没有检查账号权限或库存变化,也没有把输入自动修复。 复杂响应可用合适的运行时校验方式,仍需决定接受什么、拒绝什么。

泛型保留输入与输出的关系

一个把数字或文本原样返回的函数,若统一标注联合类型,调用后会丢失输入的具体信息。 泛型可以表达「传入什么类型,就返回什么类型」,而不是为每种输入重写函数。

echoWide(12) 返回较宽的联合类型;泛型 echo(12) 保留类型 12。 / Compare echoWide(12), returning string | number, with generic echo(12), retaining type 12.echoWide(12) 返回较宽的联合类型;泛型 echo(12) 保留类型 12。 / Compare echoWide(12), returning string | number, with generic echo(12), retaining type 12.
echoWide(12) 返回较宽的联合类型;泛型 echo(12) 保留类型 12。
ts
function echoWide(value: string | number): string | number {
  return value;
}
function echo<T>(value: T): T {
  return value;
}
const wide = echoWide(12); // string | number
const precise = echo(12); // 12

If you don't know generics, I promise you'll understand them by the end of this thread.

— Matt Pocock

把报错读成三句话

先说预期是什么、实际拿到什么、在哪层不匹配,再缩成最小复现。 例如把 wide 交给只收数字的函数:接收方要数字,但变量仍可能是文本;问题在返回类型的关系丢失。

读懂类型报错由 Archify 生成的工作流图。读懂类型报错类型报错预期是什么拿到了什么哪层不匹配最小复现根因从报错到根因错误翻译工具只是辅助,不是正确性的权威。
把类型错误拆成可查证的问题。

ts-reset 处在声明这一层

按资料采集版本,ts-reset 会调整某些内建声明,包括让 JSON 解析结果体现为未知值, 推动调用方先检查。它不提供运行时数据校验;采用前应审视项目环境与全局声明影响。

动手练习

先预测,再检查边界

  • 任务:预测 readSeats 对 { seats: 3 }、{ seats: "3" }、null 的结果,再运行核对。
  • 再解释:为何 echoWide 的结果不能直接当 number?你会修正哪一层?
参考思路

只有第一个返回 3,其余报错。echoWide 的声明允许返回文本;如果契约是原样返回,用泛型保留关系,也可在调用处检查类型。盲目断言没有证明数值条件。

完成标准

能解释断言没有验证什么,预测并运行有效与无效输入,再用普通语言说明一处类型不匹配。 还能指出泛型保留的是哪条关系,而不是只背语法。下一步看 实用类型工具。

速查

01

unknown

尚未验证,先检查再使用。

02

泛型

保留调用中输入与输出的类型关系。

03

报错

预期、实际、层次,缩小复现再修正。

来源

非官方、非商业的学习整理,与 Matt Pocock 无隶属或背书关系。所引作品版权归原作者;MIT 复用内容另附版权与许可声明。