从集合的角度去理解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类型,很多问题都会清晰不少