keyof
返回【一个对象的属性名组成的联合】
type Obj = {
a: number;
b: string;
}
type keys = keyof Obj // 'a' | 'b'
in
取出(遍历)联合类型的每一个成员类型
type U = 'a'|'b'|'c'
type Obj = {
[Prop in U]: number;
}
// 等同于
type Obj = {
a: number;
b: number;
c: number;
}
类型映射
一个类型要基于另一个类型,不想写重复代码,可以用映射:
type A = {
a: number;
b: string;
c: boolean;
}
type B = {
[prop in keyof A]: A[prop] // 相当于 B 复制了一份 A
}
映射修饰符
// 增加 只读 和 可选
type MyObj<T> = {
+readonly [P in keyof T]+?: T[P];
}
// 移除 只读 和 可选
type MyObj<T> = {
-readonly [P in keyof T]-?: T[P];
}
键名重新映射
type A = {
a: number;
b: number;
}
type B = {
[prop in keyof A as `new${prop}`]: number;
}
// 等价于:
type B = {
newa: number;
newb: number;
}
键名重新映射还可以用来进一步处理对象的属性:
type MyOmit<T, K extends keyof T> = {
[P in keyof T as P extends K ? never : P]: T[P]
}
方括号
取出对象的键值类型,如 T[K]
会返回对象 T 的属性 K 的类型
type Obj = {
a: number;
b: string;
c: boolean;
}
type T = Obj["a"] // number
type T = Obj["a" | "b"] // number | string
type T = Obj[keyof Obj] // number | string | boolean
取出所有值的类型:
- 对象:
obj[string]
:取出所有字符串属性名的值类型的联合 - 数组:
arr[number]
:取出数组中的所有值的类型的联合
条件运算
基于输入的值的类型来决定输出的值的类型:T extends U ? X : Y
(即判断 T 是否为 U 的子类型)
条件类型的分配性
如果条件运算用在【泛型】中,它就变为分布式的,最终得到联合类型的结果:
type MyExclude<T, U> = T extends U ? never : T
type A = 'a' | 'b' | 'c'
type B = 'a' | 'b'
type C = MyExclude<A, B> // 'c'
// 相当于:
// type C = MyExclude<'a', B> | MyExclude<'b', B> | MyExclude<'c', B>
infer
只能在 条件运算 的 extends
子句里出现,并且只能用在条件为真的分支中。
用来在 TS 进行推断的过程中取到对应的推断值(会尝试匹配 extends
左边的类型最接近的类型),然后继续用这个变量做运算(类似正则中的捕获组)
type T0<T> = T extends infer U ? U : never
type T1 = T0<string> // string
type T2<T> = T extends (infer U)[] ? U : never
type T3 = T2<number[]> // number
type T4 = T2<[string, number]> // string | number
is
用于描述函数的返回值是 true 还是 false:parameterName is Type
(左侧为当前函数的参数名,右侧为某一种类型)
typeof
用于【获取一个变量或者属性的类型】
let s = "hello"
let n: typeof s // let n: string
let obj = {a : 1}
let m: typeof obj.a // let m: number