TypeScript 类型体操

简单

实现 Pick

4・实现 Pickopen in new window

type MyPick<T, K extends keyof T> = {
  [key in K]: T[key]
}
1
2
3

实现 Readonly

7・实现 Readonlyopen in new window

type MyReadonly<T> = {
  +readonly [key in keyof T]: T[key]
}
1
2
3

元组转换为对象

11・元组转换为对象open in new window

前提知识:const assertionsopen in new window

type TupleToObject<T extends readonly any[]> = {
  [key in T[number]]: key
}
1
2
3

第一个元素

14・第一个元素open in new window

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

知识点:

type EmptyArray = []
type FirstElement = EmptyArray[0] // Tuple type '[]' of length '0' has no element at index '0'.
1
2

Exclude

43・Excludeopen in new window

type MyExclude<T, U> = T extends U ? never : T

type Result = MyExclude<'a' | 'b' | 'c', 'a'> // 'b' | 'c'
1
2
3

知识点:Distributive Conditional Typesopen in new window,即在X extends Y的条件类型语句中,若X是联合类型,则会将联合类型的每一个成员代入进行独立计算,再将结果组合成联合类型。

Awaited

189・Awaitedopen in new window

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

知识点:PromiseLikeopen in new window

需要确保:

  • 传给MyAwaited的类型是PromiseLike的子类型
  • 递归处理MyAwaited<Promise<Promise<string | number>>>的情况

If

268・Ifopen in new window

type If<C extends boolean, T, F> = C extends true ? T : F;
1

Concat

533・Concatopen in new window

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

知识点:

Push/Unshift

type Push<T extends any[], U> = [...T, U]
type Unshift<T extends any[], U> = [U, ...T];
1
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

中等

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

Omit

3・Omitopen in new window

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