类型层级
类型层级能帮助明确各种类型的层级与兼容性。以下,从底层到顶层。
判断类型兼容性
通过 extends
关键字可以判断前者类型是否为后者类型的子类型。
ts
type IsChild = 'foo' extends string ? true : false;
最底层 never 类型
never 代表虚无,它是任何类型的子类:
ts
type Res19 = never extends 'xxx' ? true : false; // true
层级
never < 字面量类型
字面量类型与原始类型
ts
type IsStringChild = 'foo' extends string ? true : false;
type IsNumberChild = 1 extends number ? true : false;
type IsBooleanChild = true extends boolean ? true : false;
type IsObjectChild1 = {} extends object ? true : false;
type IsObjectChild2 = { name: string } extends object ? true : false;
type IsObjectChild3 = [] extends object ? true : false;
层级
字面量类型 < 对应的原始类型
装箱类型
装箱类型:String
,Object
ts
type Res1 = string extends String ? true : false; // true
type Res2 = String extends {} ? true : false; // true
type Res3 = {} extends object ? true : false; // true
type Res4 = object extends Object ? true : false; // true
type Res5 = string extends object ? true : false; // false
{} 与 object/Object
ts
type Res6 = {} extends object ? true : false; // true
type Res7 = object extends {} ? true : false; // true
type Res8 = {} extends Object ? true : false; // true
type Res9 = Object extends {} ? true : false; // true
{} extends
和extends {}
是两种不同的比较方式。
{} extends object
和{} extends Object
是将{}
看作为object
和Object
的字面量类型,是从类型信息的层面发出的,即字面量类型在基础类型之上提供了更详细的类型信息。
object extends {}
和Object extends {}
是从结构化类型系统的比较发出的。即{}
作为一个空对象,它的结构是最简单的,所以它可以兼容任何对象类型,视作是所有类型的基类。
object 与 Object
ts
type Res10 = Object extends object ? true : false; // true
type Res11 = object extends Object ? true : false; // true
在系统设定中:
Object
包含了所有除 Top Type 以外的类型:基础类型、函数类型等。
object
包含了所有非原始类型的类型:数组、对象、函数。
所以从类型信息层面出发:
层级
原始类型 < 原始类型对应的装箱类型 < Object 类型
Top Type
类型层级的顶端只有any
和unknown
两种类型。
ts
type Res12 = Object extends any ? true : false; // true
type Res13 = Object extends unknown ? true : false; // true
但是如果倒过来,unknown
没什么问题,any
就是true|false
了。
ts
type Res15 = unknown extends Object ? true : false; // false
type Res14 = any extends Object ? true : false; // true | false
type Res16 = any extends string ? true : false; // true | false
type Res17 = any extends 1 ? true : false; // true | false
type Res18 = any extends never ? true : false; // true | false
type Res23 = any[] extends number[] ? true : false; // true
因为系统设定中,any
代表了任何可能的类型。any
可以赋值给任何类型,但是unknown
只能赋值给unknown
和any
。
ts
let x: string
const b: any = 'xxx'
x = b
let c: unknown
x = c // error
any
和unknown
也是互相兼容的。
所以:
层级
Object < any / unknown
总结
层级 | 类型 |
---|---|
Top Type | any 、unknown |
顶级原型(原型链顶端) | Object |
装箱类型 | String 、Number 、Boolean |
原始类型(基础类型、拆箱类型) | string 、number 、boolean |
字面量类型 | 'xxx' 、1 、true |
Bottom Type | never |
拓展:装箱和拆箱类型
装箱类型:值类型向引用类型转换
拆箱类型:引用类型向值类型转换