any类型
在 TypeScript 中,任何类型都可以被归为 any 类型。这让 any 类型成为了类型系统的 顶级类型 (也被称作 全局超级类型)。
这是一些我们赋值给 any 类型的代码示例:
// demo1
let value: any;
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
// demo2
let value: any;
value.foo.bar; // OK
value.trim(); // OK
value(); // OK
new value(); // OK
value[0][1]; // OK
这许多场景下,这样的机制都太宽松了。使用any类型,可以很容易地编写类型正确但是执行异常的代码。如果我们使用 any 类型,就无法享受 TypeScript 大量的保护机制。
unknow类型
就像所有类型都可以被归为 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 类型本身。
假如对unknow类型执行某些操作,看看接下来会发生什么
let value: unknown;
value.foo.bar; // Error
value.trim(); // Error
value(); // Error
new value(); // Error
value[0][1]; // Error
将 value 变量类型设置为 unknown 后,这些操作都不再被认为是类型正确的
小结:
- 定义为unknown类型和any类型的变量可以进行重复赋值
- 不允许对unknow类型的变量执行任意操作,而对any类型的变量进行任意操作不会有任何问题
操作unknown类型
我们可以通过不同的方式将 unknown 类型缩小为更具体的类型范围,包括 typeof 运算符,instanceof 运算符和自定义类型保护函数。
对unknown类型使用类型断言
前一节中,我们缩小了unknown类型的范围,并指定了其可能的具体类型,针对具体类型再执行安全的操作,这是比较推荐的做法。
如果要强制编译器信任类型为unknown的值为给定类型,则可以使用类型断言:
const value: unknown = "Hello World";
const someString: string = value as string;
const otherString = someString.toUpperCase(); // "HELLO WORLD"
如果我们确定unknow类型的具体类型,则使用断言不会有任何问题。假如错误地指定了类型,并执行了错误操作,可能会导致运行时错误。
联合类型中的unknown类型
type UnionType1 = unknown | null; // unknown
type UnionType2 = unknown | undefined; // unknown
type UnionType3 = unknown | string; // unknown
type UnionType4 = unknown | number[]; // unknown
type UnionType5 = unknown | any; // any
除any之外,unknow类型可以吸收任何类型。
交叉类型中的unknown类型
type IntersectionType1 = unknown & null; // null
type IntersectionType2 = unknown & undefined; // undefined
type IntersectionType3 = unknown & string; // string
type IntersectionType4 = unknown & number[]; // number[]
type IntersectionType5 = unknown & any; // any
在交叉类型中,包含unknow类型不会改变结果。