前言
由于 any / unknown 类型几乎 “相似” ,所以可以直接一起学习。
在 Typescript 中,当我们不确定一个类型是什么类型的,可以选择给其声明为 any 或者 unkown。
本文会介绍这两种类型的介绍及其示例用法,最后谈一下二者的区别。
any 类型
在 TypeScript 中,任何类型都可以被归为 any 类型,因为它可以被赋予任何值。
这让 any 类型成为了类型系统的顶级类型(也被称作全局超级类型),如下代码所示:
let notSure: any = 666;
notSure = "王佳斌";
notSure = false;
TypeScript 允许我们对 any 类型的值执行任何操作,而无需事先执行任何形式的检查,如下代码所示:
let value: any;
value.foo.bar; // OK
value.trim(); // OK
value(); // OK
new value(); // OK
value[0][1]; // OK
在许多场景下,这太宽松了。使用 any 类型,可以很容易地编写类型正确但在运行时有问题的代码。
如果您使用 any 类型,就无法使用 TypeScript 提供的大量的保护机制。
unknown 类型
为了解决 any 带来的问题,TypeScript 3.0 引入了 unknown 类型。
就像所有类型都可以赋值给 any,所有类型也都可以赋值给 unknown。
这使得 unknown 成为 TypeScript 类型系统的另一种顶级类型(另一种是前面的 any),如下代码所示:
let value: unknown;
value = true; // OK
value = 42; // OK
value = "Hello World"; // OK
value = []; // OK
value = {}; // OK
value = Math.random; // OK
value = null; // OK
value = undefined; // OK
value = new TypeError(); // OK
value = Symbol("type"); // OK
对 value 变量的所有赋值都被认为是类型正确的。
但是,当我们尝试将类型为 unknown 的值赋值给其他类型的变量时会发生什么?
let value: unknown;
let value1: unknown = value; // OK
let value2: any = value; // OK
let value3: boolean = value; // Error
let value4: number = value; // Error
let value5: string = value; // Error
let value6: object = value; // Error
let value7: any[] = value; // Error
let value8: Function = value; // Error
unknown 类型只能被赋值给 any 类型和 unknown 类型本身。直观地说,这是有道理的:只有能够保存任意类型值的容器才能保存 unknown 类型的值。毕竟我们不知道变量 value 中存储了什么类型的值。
现在让我们看看当我们尝试对类型为 unknown 的值执行操作时会发生什么。以下是我们在之前 any 看过的相同操作:
let value: unknown;
value.foo.bar; // Error
value.trim(); // Error
value(); // Error
new value(); // Error
value[0][1]; // Error
将 value 变量类型设置为 unknown 后,这些操作都不再被认为是类型正确的。通过将 any 类型改变为 unknown 类型,我们已将允许所有更改的默认设置,更改为禁止任何更改。
二者区别
其实很明显,可以用以下表格表示。
相同点 | 不同点 |
都可以赋予任意类型的值 | unknown 类型的值不能直接赋值给其他变量 |