TypeScript 类型体操
简单
实现 Pick
type MyPick<T, K extends keyof T> = {
[key in K]: T[key]
}
1
2
3
2
3
实现 Readonly
7・实现 Readonlyopen in new window
type MyReadonly<T> = {
+readonly [key in keyof T]: T[key]
}
1
2
3
2
3
元组转换为对象
前提知识:const assertionsopen in new window
type TupleToObject<T extends readonly any[]> = {
[key in T[number]]: key
}
1
2
3
2
3
第一个元素
type First<T extends any[]> = T extends [] ? never : T[0]
// 这种方式也行,但是上面的方法更好
type First<T extends any[]> = T[0] extends T[number] ? T[0] : never
1
2
3
4
2
3
4
知识点:
type EmptyArray = []
type FirstElement = EmptyArray[0] // Tuple type '[]' of length '0' has no element at index '0'.
1
2
2
Exclude
type MyExclude<T, U> = T extends U ? never : T
type Result = MyExclude<'a' | 'b' | 'c', 'a'> // 'b' | 'c'
1
2
3
2
3
知识点:Distributive Conditional Typesopen in new window,即在X extends Y
的条件类型语句中,若X
是联合类型,则会将联合类型的每一个成员代入进行独立计算,再将结果组合成联合类型。
Awaited
interface MyPromiseLike<T> { then: (onfulfilled: (arg: T) => any) => any }
type MyAwaited<T extends MyPromiseLike<any>> = T extends MyPromiseLike<infer R>
? R extends MyPromiseLike<any>
? MyAwaited<R>
: R
: T;
1
2
3
4
5
6
7
2
3
4
5
6
7
知识点:PromiseLikeopen in new window
需要确保:
- 传给
MyAwaited
的类型是PromiseLike
的子类型 - 递归处理
MyAwaited<Promise<Promise<string | number>>>
的情况
If
type If<C extends boolean, T, F> = C extends true ? T : F;
1
Concat
type Concat<T extends any[], U extends any[]> = [...T, ...U]
1
知识点:Tupleopen in new window类型可以扩展运算符(...
)来创建新的类型。
Includes
898・Includesopen in new window
type IEqual<T,U> =
(<X>()=>X extends T ? 1 : 2) extends
(<X>()=>X extends U ? 1 : 2) ? true :false
type Includes<T extends readonly any[], U> = T extends [infer V, ...infer R]
? IEqual<V, U> extends true
? true
: Includes<R, U>
: false;
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
知识点:
- 如何判断两个类型相等?Feature request - type level equal operatoropen in new window
- 通过 infer + IEqual 递归调用,确定 U 与 T 里的某个类型相等。
Push/Unshift
type Push<T extends any[], U> = [...T, U]
type Unshift<T extends any[], U> = [U, ...T];
1
2
2
知识点:同 Concat
Parameters
3312・Parametersopen in new window
const foo = (arg1: string, arg2: number): void => {};
// 实现
type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer Args extends any[]) => any
? Args
: never
type FunctionParamsType = MyParameters<typeof foo> // [arg1: string, arg2: number]
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
中等
Get Return Type
2・Get Return Typeopen in new window
const fn = (v: boolean) => {
if (v)
return 1;
else
return 2;
};
// 实现
type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type a = MyReturnType<typeof fn> // should be "1 | 2"
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Omit
interface Todo {
title: string;
description: string;
completed: boolean;
}
// 实现
type MyOmit<T, K extends keyof T> = {
[key in Exclude<keyof T, K>]: T[key]
}
type TodoPreview = MyOmit<Todo, 'description' | 'title'>
const todo: TodoPreview = {
completed: false,
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16