结论:优先用unknown,慎用any;unknown强制类型守卫保障安全,any彻底放弃检查导致运行时风险。

直接说结论:any 是类型检查的“断电开关”,unknown 是类型安全的“安检门”。选哪个,关键看你要不要为变量的后续使用负责。
any:完全放弃类型检查,灵活但危险
声明为 any 的变量,TypeScript 编译器会彻底“睁一只眼闭一只眼”:
- 可以被赋值为任何类型(string、number、object、function 都行)
- 可以调用任意方法、访问任意属性,哪怕该操作在运行时一定会报错(比如对数字调用
.toUpperCase()) - 可以被直接赋给其他具体类型,无需验证(
let n: number = valueAny;合法) - 适合极少数场景:快速迁移旧 JS 代码、对接无类型定义的第三方库、临时绕过类型系统调试
unknown:接受一切输入,但拒绝一切盲操作
unknown 同样能接收所有类型的值,但编译器会强制你在使用前“验明正身”:
- 赋值自由(
let v: unknown = fetchResult;没问题) - 但直接调用方法、访问属性、参与运算都会报错(
v.toString()→ “Object is of type 'unknown'”) - 必须通过
typeof、instanceof、自定义类型守卫或类型断言(as)缩小范围后才能安全使用 - 不能直接赋给
string、number等具体类型(let s: string = vUnknown;报错)
类型安全怎么选:优先 unknown,慎用 any
只要不是迫不得已,把 any 替换成 unknown 是最直接的安全升级:
- 处理 API 响应、用户输入、localStorage 数据等外部不可信来源时,一律用
unknown - 写通用工具函数(如深克隆、序列化)时,参数类型优先设为
unknown,再做运行时判断 - 当确实需要绕过检查(比如 mock 测试、动态插件加载),先用
unknown,再配合as或类型守卫显式转换 - 团队可开启
noImplicitAny编译选项,从源头禁止隐式any,倒逼使用unknown+ 类型守卫
一个典型对比示例
假设从接口拿到一个不确定结构的响应:
- 用
any:const data: any = await api.getData(); console.log(data.name.toUpperCase());—— 编译通过,但data可能是null或没有name,运行时报错 - 用
unknown:const data: unknown = await api.getData(); if (data && typeof data === 'object' && 'name' in data && typeof data.name === 'string') { console.log(data.name.toUpperCase()); }—— 编译检查到位,错误在开发阶段暴露











