携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
前言
TypeScript 在开发中,除了基本的内置类型之外,更多时候需要的是由内置类型通过一定方式组合而成的新类型,或者叫做自定义类型。
一般有四种方式用于创建自定义类型:联合、交叉、索引、映射。
最近正好学习到了这一部分,总结记录一下,先来聊聊联合类型、交叉类型。
联合类型
主要标志就是使用 | 运算符,类似逻辑运算的或操作, 表示满足指定类型的任意一种即可,比如:
type Union = number | string
表示 Union 类型可以是 number 或者 string,这里两个类型的值都符合 Union 的要求。
但也有一些特殊的情况,如下:
type Union1 = number | any | string
当联合类型中存在 any 时,Union1 只会是 any 类型,因为 any 本身就包含着所有的内置类型,也就包含着 number 和 string,所以最后会被推导为一个 any:
当联合类型中存在 unknown,与 any 也是同理,因为 unknown 类型的值也可以是任何类型,自然也就包括 number,所以会被推导为 unknown:
type Union2 = number | unknown
当联合类型中存在 never 时,never 会被忽略掉;
type Union3 = number | never | string
因为 never 本身代表什么都没有,没有任何数据可以赋值给 never 类型,所以,联合类型中会将其剔除。
交叉类型
主要标志是使用 & 运算符,类似逻辑运算的与操作,表示要同时满足全部的指定类型,比如:
type Cross = { name: string } & { age: number }
上面代码意味着 Cross 这个类型的对象,必须同时拥有 name 和 age 这两个属性,并且属性的值还得分别是 string 和 number。
但是如果对象中的存在相同的属性,并且属性的值的类型不同,则会变成 never:
type Cross = { name: string } & { age: number, name: boolean } // never
需要注意的是,内置类型的交叉类型基本都是 never:
type Cross1 = number & string // never
type Cross2 = string & boolean // never
type Cross3 = string & symbol // never
type Cross4 = number & object // never
type Cross5 = number & null // never
type Corss6 = number & undefined // never
type Cross7 = object & null // never
type Cross8 = number & never // never
因为不可能存在一个数据既是 A 又是 B 的,所以全部都为 never。
当然,也有特殊情况,当交叉类型存在 any 时,结果皆为 any:
type Cross8 = any & number // any
never 也是如此,甚至连 any & never 的结果都是 never:
而与 unknown 参与的 交叉类型 与 any 和 never 相反,类似于 联合类型 中的 never,本身会被忽略掉:
type Cross14 = number & unknown // number
type Cross15 = string & unknown // string
type Cross16 = any & unknown // any
type Cross17 = never & unknown // never