推荐一个学习 typescript 的网站: https://www.typescript-training.com/
再推荐一个 ts-challenges
条件类型
举个🌰:
1
2
3
4
5
6
7
8
9
|
type Diff<T, U> = T extends U ? never : T; // 移除 T 中可以赋值给 U 的类型
type Filter<T, U> = T extends U ? T : never; // 移除 T 中不可以赋值给 U 的类型
type NonNullable<T> = Diff<T, null | undefined>; // 移除 T 中为 null 或 undefined 的类型
type T30 = Diff<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d"
type T31 = Filter<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "a" | "c"
type T34 = NonNullable<string | number | undefined>; // string | number
type T35 = NonNullable<string | string[] | null | undefined>; // string | string[]
|
条件类型通常会结合 映射类型 一起使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
type FunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
type FunctionProperties<T> = Pick<T, FunctionPropertyNames<T>>;
type NonFunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? never : K;
}[keyof T];
type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>;
interface Part {
id: number;
name: string;
subparts: Part[];
updatePart(newName: string): void;
}
type T40 = FunctionPropertyNames<Part>; // "updatePart"
type T41 = NonFunctionPropertyNames<Part>; // "id" | "name" | "subparts"
type T42 = FunctionProperties<Part>; // { updatePart(newName: string): void }
type T43 = NonFunctionProperties<Part>; // { id: number, name: string, subparts: Part[] }
|
infer
关键字
可以使用 infer
来定义要推断的类型变量。例如获取函数的返回类型:
1
2
3
|
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
type T0 = ReturnType<() => string>; // string
|
获取属性类型:
1
2
3
|
type Foo<T> = T extends { a: infer U; b: infer U } ? U : never;
type T1 = Foo<{ a: string; b: number }>; // string | number
|
获取函数参数类型:
1
2
3
4
5
6
|
type Bar<T> = T extends { a: (x: infer U) => void; b: (x: infer U) => void }
? U
: never;
type T20 = Bar<{ a: (x: string) => void; b: (x: string) => void }>; // string
type T21 = Bar<{ a: (x: string) => void; b: (x: number) => void }>; // string & number 其实也就是 never
|
获取构造函数中参数类型:
1
2
3
|
type ConstructorParameters<T> = T extends new (...args: infer R) => any
? R
: never;
|
获取实例类型:
1
|
type InstanceType<T> = T extends new (...args: any[]) => infer R ? R : any;
|
使用示例
数组示例
1
2
3
4
|
type Pop<T extends unknown[]> = T extends [...infer U, unknown] ? U : T
type Push<T extends unknown[], U> = [...T, U]
type Shift<T extends unknown[]> = T extends [unknown, ...infer U] ? U : T
type Unshift<T extends unknown[], U> = [U, ...T]
|
字符串示例
1
2
3
4
|
type Blank = '\t'| '\n' | ' '
type TrimLeft<S extends string> = S extends `${Blank}${infer R}` ? TrimLeft<R> : S;
type TrimRight<S extends string> = S extends `${infer R}${Blank}` ? TrimRight<R> : S;
type Trim<S extends string> = TrimLeft<TrimRight<S>>;
|