TS-any, unknown有什么区别

284 阅读2分钟

从集合的角度去理解TS类型,这个问题会清晰很多

例子

普通类型,string,number看作一个集合,那'year'、'month'、2020,就是相比与他们更小的子集;

所以可以这样:

let time: string = 'year';
time = 'month';

let age: number = 2020;

即子集可以赋值给超集,反过来就不行,不同的集合也不能相互赋值

let time2: 'year' = time; // error
time2 = 'month'; // error

let age2: 2020 = age; // error
age2 = 2021; // error

将object看做一个集合,Function, Record<any, string>是一个被包含的更小的子集,(name: string)=>void, {name: string}, 是基于前者的更小的子集。

所以可以这样:

let obj: object = {'name': 'zenos'};
let objRecord: Record<string, string> = {name: 'zenos'};
let func: Function = (name: string)=>{}

obj = objRecord;
obj = func;

objRecord = obj; //error
objRecord = func // error

我们使用TS的很多复杂的类型工具,目的就是使定义的类型集合更小一点

object类型很宽泛,所以想要在上面获取任何非普通类型的非共同属性,就会报错。因为object类型为一个很大的超集,所以实际变量值有可能是一个Map,一个Array,一个Function,一个普通对象等等

obj.name //error
obj.length // error

unknown

而unknown就是所有类型的超集,是TS类型的全集,即可能是任意的类型,所以可以将任何类型变量赋值给unknown类型变量,而unknown类型变量只能赋值给unknown类型。并且在unknown类型的变量上调用任何的属性都会用报错。

any

而any有着和unknown相同的类型范围,包含了所有类型,但any又可以赋值给任意的类型的变量。所以对于any再用集合的概念就不合适了,可以理解为TS对any放弃检查了,any类型的变量可以为所欲为,完全超脱TS规则的限制。

总结

从集合的角度去理解TS类型,很多问题都会清晰不少