TypeScript 中 any 和 unknown 的区别
在 TypeScript 中,有两个经常用来表示“任意类型”的关键字:any 和 unknown。它们看似相似,但在安全性和使用场景上差别很大。本文从五个方面来详细解析。
any 是什么
any 表示“可以是任意类型”。使用 any 相当于告诉 TypeScript 编译器“不要对这个值做任何类型检查”。
let value: any;
value = 1; // ✅
value = 'hello'; // ✅
value = true; // ✅
// 直接访问属性/方法也不会报错
value.foo(); // ✅
let num: number = value; // ✅ 任意赋值
特点:
any可接收任意类型值,也可赋给任意类型变量。- 使用时不会进行任何编译期类型检查。
- 是最不安全的类型,相当于“放弃了 TypeScript”。
unknown 是什么
unknown 也表示“可以是任意类型”,但与 any 不同,必须在使用前进行类型检查或类型断言,否则编译器不允许访问其属性或方法。
let value: unknown;
value = 1;
value = 'hello';
value = true;
// value.foo(); ❌ 报错,必须先缩小类型
if (typeof value === 'string') {
console.log(value.toUpperCase()); // ✅ 类型缩小后可用
}
let num: number = value as number; // ✅ 断言后可赋值
特点:
unknown可接收任意类型值,但不能直接赋给除any/unknown外的变量。- 不能直接访问属性或方法,必须先缩小类型或断言。
- 是
any的类型安全替代方案。
使用场景
any 的典型场景:
- 从 JavaScript 项目快速迁移到 TypeScript 时,临时跳过类型检查。
- 原型验证或实验性代码阶段,不想写类型。
unknown 的典型场景:
-
函数返回值类型不确定时,例如
JSON.parse():function parse(str: string): unknown { return JSON.parse(str); } -
外部输入(用户输入、接口返回)类型不确定时,既想保持灵活,又想有类型保护。
区别
| 特性 | any | unknown |
|---|---|---|
| 类型检查 | 不检查,完全放行 | 必须先检查或断言后使用 |
| 赋值自由度 | 任意赋值给任何类型 | 只能赋给 any / unknown,否则需断言 |
| 属性/方法访问 | 直接可用,不报错 | 不可直接访问,需缩小类型 |
| 安全性 | 低 | 高 |
| 推荐程度 | 不推荐(除非迫不得已) | 推荐(在不确定类型时) |
总结
any是完全关闭类型检查的“逃生舱”,用起来方便但会失去类型系统的保护。unknown是类型安全的“任意类型”,用之前必须检查或断言,能更好地利用 TypeScript 的类型系统。- 原则:如果不确定值的类型但仍希望安全,优先使用
unknown;any仅在不得已时使用。
通过正确选择
any和unknown,既能写出灵活的代码,又能保持类型安全,让 TypeScript 真正发挥作用。