常用运算
- 条件 extends ?
type First<T> = T extends [infer R, ...any[]] ? R : never
- 约束 extends
type TupleToObject<T extends readonly any[]> = { [P in T[number]]: P }
extends在类型操作中有narrow的作用,1、在=右边可以用作条件,判断extends的左边是否可赋值(兼容)右边 ;2、在等号左边,可以约束左边的边界。
- 推导 infer
type First<T> = T extends [infer R, ...any[]] ? R : never
一般情况下,infer都会和infer进行搭配做提取推导操作,可参看下面的模式匹配做提取,当然其实可以结合递归实现更复杂的操作。
- 联合 |
type Numeric = number | string
- 交叉 &
type T = { a: string } & { b: boolean }
- 索引查询 keyof
type Key<T> = keyof T
- 索引访问 []
type Length<T extends readonly any[]> = T['length']
通常情况下,用索引访问时,取得是对应键对应的类型。但对于数组来说,有一点特殊:
type TArr = ['0', '1', '2']
type Ta = TArr[number] // '0' | '1' | '2'
type Ta2 = TArr['length'] // 3
const MyArray = [
{ name: "Alice", age: 15 },
{ name: "Bob", age: 23 },
{ name: "Eve", age: 38 },
];
type Person = typeof MyArray[number];
// type Person = {
// name: string;
// age: number;
// }
- 索引遍历 in (一般和keyof搭配)
type Readonly<T> = { readonly [P in keyof T]: T[P] }
- 索引重映射 as
type MapType<T> = {
[Key in keyof T as `${Key & string}${Key & string}`]: [T[Key], T[Key]]
}
常用模式
- 模式匹配做提取
type GetParameters<Func extends Function> =
Func extends (...args: infer Args) => unknown ? Args : never;
type ParametersResult = GetParameters<(name: string, age: number) => string>
- 重新构造做变换
type CapitalizeStr<Str extends string> =
Str extends `${infer First}${infer Rest}`
? `${Uppercase<First>}${Rest}` : Str;
type CapitalizeResult = CapitalizeStr<'tang'>
- 递归复用做循环
type TrimLeft<T extends string> = T extends ` ${infer R}` ? TrimLeft<R> : T;
type value = TrimLeft<" value">
- 数组长度做计数
type BuildArray<
Length extends number,
Ele = unknown,
Arr extends unknown[] = []
> = Arr['length'] extends Length
? Arr
: BuildArray<Length, Ele, [...Arr, Ele]>;
type Add<Num1 extends number, Num2 extends number> =
[...BuildArray<Num1>, ...BuildArray<Num2>]['length'];
type AddResult = Add<32, 25>
实现内置类型
type TPartial<T> = {
[P in keyof T]?: T[P];
}
type TRequired<T> = {
[P in keyof T]-?: T[P]
}
type TReadonly<T> = {
readonly [P in keyof T]: T[P]
}
type TPick<T, K extends keyof T> = {
[P in K]: T[P]
}
type TRecord<K extends keyof any, T> = {
[P in K]: T
}
type TExclude<T, U> = T extends U ? never : T
type TExtract<T, U> = T extends U ? T : never
type TOmit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type TAwaited<T> =
T extends null | undefined
? T
: T extends object & { then(onfulfilled: infer F): any }
? F extends ((value: infer V, ...args: any) => any)
? Awaited<V>
: never
: T