TypeScript 中的 unknown 与 any
说明 unknown 与 any 的根本差异、各自适用场景,以及为什么 unknown 更适合作为不可信输入的默认类型。
#tech / dev
#resource / typescript
#type / concept
#status / growing
[!info] related notes
- 所属 MOC: TypeScript MOC
- 总览页: TypeScript
- 并列概念: TypeScript 类型检查
- 速记入口: TypeScript 速记
TypeScript 中的 unknown 与 any
一句话定义
any 会直接绕过类型系统,而 unknown 会保留“这个值还不可信”的信息,要求你在使用前先做类型缩小。
核心机制 / 工作原理
any 在做什么
当一个值被标成 any 时,TypeScript 基本停止对它继续追责。你可以:
- 访问任意属性
- 调用任意方法
- 把它赋给几乎任何别的类型
它更像一种逃生舱。
unknown 在做什么
unknown 也能接收任何值,但在你证明它是什么之前,你不能直接使用它的结构。
这会强迫你先做:
typeofinstanceofin- 自定义类型谓词
最小例子 / 最小场景
any
let value: any = 10;
value.toUpperCase(); // 编译通过,但运行时报错
unknown
let value: unknown = "hello";
if (typeof value === "string") {
value.toUpperCase();
}
核心区别对照表
| 特性 | any (顶级类型) | unknown (顶级类型) |
|---|---|---|
| 可赋值性 | 任何类型都能赋给 any | 任何类型都能赋给 unknown |
| 操作权限 | 允许访问任何属性、调用任何方法 | 不允许访问属性或调用方法 |
| 赋值给他人 | 可以赋值给除 never 外的任何类型 | 只能赋值给 unknown 或 any |
| 安全性 | 极低(绕过类型检查) | 极高(强制类型检查) |
使用场景建议
更推荐 unknown 的场景
- 外部 API 返回值
JSON.parse()的结果- 用户输入
- 第三方 SDK 给出的未知结构
- 需要逐步收窄的数据入口
any 还能在哪些场景暂时出现
- JS 向 TS 迁移初期的过渡区
- 类型信息确实不存在、又需要先把流程跑通的极小范围
- 第三方类型极度不完整时的局部兜底
默认原则仍然是:能用 unknown 就不要先上 any。
边界与易混淆点
unknown 不是“更麻烦的 any”
它的价值就在于保留“不确定性”,逼你把风险显式处理掉。
as 断言会削弱 unknown 的价值
如果把 unknown 立即断成具体类型,那么它带来的保护会迅速消失。