枚举类型 enum:
枚举就是将一组可能出现的值,一个个列举出来,定义在一个类型中,使用 enum 关键字来定义,这个类型就是枚举类型。
枚举类型允许开发者定义一组命名的常量。
// 定义枚举类型
enum Direction {
LEFT,
RIGHT,
}
// 使用枚举类型
const turnDirection = (direction: Direction) => {
switch (direction) {
case Direction.LEFT:
console.log('向左移动一个格子')
break
case Direction.RIGHT:
console.log('向右移动一个格子')
break
}
}
turnDirection(Direction.LEFT)
枚举项的值:
枚举项默认会被赋值为从 0 开始递增的数字。
可以给枚举项手动赋数字类型的值,正负数、整数浮点数都可以。未手动赋值的枚举项会接着上一个枚举项递增,递增步长为 1。
enum Direction {
LEFT = -10.5,
RIGHT,
}
也可以给枚举项赋字符串类型的值,但此时后面的枚举项就无法递增了,必须显式地赋值,否则就会报错。
enum Direction {
LEFT, // 正确。给枚举项赋字符串类型的值后,前面的枚举项无须显式地赋值,默认值还是从 0 开始的数字
RIGHT = 'right',
UP, // 错误。给枚举项赋字符串类型的值后,后面的枚举项必须显式地赋值
}
映射类型:
有时候,一个类型需要基于另外一个类型,但是又不想手动拷贝一份,此时就可以使用映射类型。
映射类型必须使用 type 来定义,不能使用 interface。可以把映射类型想象成是一个函数,调用它之后就会拷贝出来一份类型。
// 1. 定义一个类型
type PersonType = {
name: string,
age: number,
}
// 2. 定义映射类型
// 使用 type 定义一个映射类型的名称,然后通过泛型接收一个类型,使其等于一个对象类型
type MapType<Type> = {
// 基于索引签名。通过 keyof Type 拿到 Type 中的每个 key,然后依次作用一次,其实就相当于遍历了一次
[property in keyof Type]: Type[property]
// 其实就相当于:
// name: PersonType['name'] --> string,
// age: PersonType['age'] --> number,
}
// 3. 调用映射类型拷贝出来一份类型
type newPersonType = MapType<PersonType>
映射类型的修饰符:
?
:用于设置属性可选。- readonly:用于设置属性只读。
拷贝的过程中可以使用修饰符对原来的类型进行转变。修饰符的前面还可以加 +
或者 -
的符号来表示添加或者删除修饰符,默认是 +
。
type PersonType = {
name: string,
age: number,
}
type MapType<Type> = {
// 添加 ? 修饰符使得拷贝后的所有属性都变成可选属性
[property in keyof Type]?: Type[property]
// 就相当于是:
// [property in keyof Type]+?: Type[property]
}
type newPersonType = MapType<PersonType>
条件类型:
条件类型用来帮助描述输入类型和输出类型之间的关系。语法类似于 JavaScript 中的三元运算符 someType extends OtherType ? TrueType : falseType
,根据前面的条件来决定返回哪个结果。
type IDType = number | string
type resType = number extends IDType ? true : false
// 参数只能接受 number 类型和 string 类型,并且必须同时为 number 类型或者 string 类型;返回值如果不是 number 类型,就是 string 类型
function sum<T extends number | string>(num1: T, num2: T): T extends number ? number : string
function sum(num1, num2) {
return num1 + num2
}
const res1 = sum(1, 2) // 正确
const res2 = sum('a', 'b') // 正确
const res3 = sum(1, 'a') // 错误。参数类型不一致
在条件类型中推断:
条件类型提供了 infer 关键字,可以从正在比较的类型中推断类型,然后在 true 分支里引用该推断结果。
// 如果泛型 T 是继承自函数类型,就在条件类型中推断函数的返回值并返回,否则返回 never
// R 只是一个标识符,可以任意命名
T extends (...args: any[])=>infer R ? R : never
分发联合类型:
当在泛型中使用条件类型的时候,如果传入的是一个联合类型,就会变成分发的,这个条件类型会依次应用到联合类型中的每个成员,将联合类型中的每个成员挨个执行一次。
type toArray<T> = T[]
// 此时获取到的是 (string | number)[],但实际上想要是 string[] | number[]
type numberArray = toArray<number | string>
// 此时,相当于是 toArray<string> | toArray<number>
type toArray<T> = T extends any ? T[] : never
type numberArray = toArray<number | string>