实现 Pick

实现 TS 内置的 Pick,但不可以使用它。从类型 T 中选择出属性 K,构造成一个新的类型。例如:

  1. interface Todo {
  2. title: string
  3. description: string
  4. completed: boolean
  5. }
  6. type TodoPreview = MyPick<Todo, 'title' | 'completed'>
  7. const todo: TodoPreview = {
  8. title: 'Clean room',
  9. completed: false,
  10. }

实现:

  1. type Pick<T, K extends keyof T> = {
  2. [P in K]: T[P]
  3. }

实现 Readonly

不要使用内置的Readonly,自己实现一个。该 Readonly 会接收一个 泛型参数,并返回一个完全一样的类型,只是所有属性都会被 readonly 所修饰。也就是不可以再对该对象的属性赋值。例如:

  1. interface Todo {
  2. title: string
  3. description: string
  4. }
  5. const todo: MyReadonly<Todo> = {
  6. title: "Hey",
  7. description: "foobar"
  8. }
  9. todo.title = "Hello" // Error: cannot reassign a readonly property
  10. todo.description = "barFoo" // Error: cannot reassign a readonly property

实现:

  1. type Readonly<T> = {
  2. readonly [P in keyof T]: T[P]
  3. }

元组转换为对象

传入一个元组类型,将这个元组类型转换为对象类型,这个对象类型的键/值都是从元组中遍历出来。例如:

  1. const tuple = ['tesla', 'model 3', 'model X', 'model Y'] as const
  2. type result = TupleToObject<typeof tuple> // expected { tesla: 'tesla', 'model 3': 'model 3', 'model X': 'model X', 'model Y': 'model Y'}

实现:

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

第一个元素

实现一个通用First,它接受一个数组T并返回它的第一个元素的类型。例如:

  1. type arr1 = ['a', 'b', 'c']
  2. type arr2 = [3, 2, 1]
  3. type head1 = First<arr1> // expected to be 'a'
  4. type head2 = First<arr2> // expected to be 3

实现:

  1. type First<T extends any[]> = T[0]

获取元素长度

创建一个通用的Length,接受一个readonly的数组,返回这个数组的长度。例如:

  1. type tesla = ['tesla', 'model 3', 'model X', 'model Y']
  2. type spaceX = ['FALCON 9', 'FALCON HEAVY', 'DRAGON', 'STARSHIP', 'HUMAN SPACEFLIGHT']
  3. type teslaLength = Length<tesla> // expected 4
  4. type spaceXLength = Length<spaceX> // expected 5

实现:

  1. type Length<T extends any[]> = T extends { length: number } ? T['length'] : never

Exclude

实现内置的Exclude 类型,但不能直接使用它本身。从联合类型 T 中排除 U 的类型成员,来构造一个新的类型。例如:

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

实现:

  1. type Exclude<T, U> = T extends U ? never : T

Awaited

假如我们有一个 Promise 对象,这个 Promise 对象会返回一个类型。在 TS 中,我们用 Promise 中的 T 来描述这个 Promise 返回的类型。请你实现一个类型,可以获取这个类型。例如:Promise,请你返回 ExampleType 类型。

  1. type ExampleType = Promise<string>
  2. type Result = MyAwaited<ExampleType> // string

实现:

  1. type MyAwaited<T> = T extends Promise<infer I> ? I : never

If

实现一个 IF 类型,它接收一个条件类型 C ,一个判断为真时的返回类型 T ,以及一个判断为假时的返回类型 F。 C 只能是 true 或者 false, T 和 F 可以是任意类型。例如:

  1. type A = If<true, 'a', 'b'> // expected to be 'a'
  2. type B = If<false, 'a', 'b'> // expected to be 'b'

实现:

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

Concat

在类型系统里实现 JavaScript 内置的 Array.concat 方法,这个类型接受两个参数,返回的新数组类型应该按照输入参数从左到右的顺序合并为一个新的数组。例如:

  1. type Result = Concat<[1], [2]> // expected to be [1, 2]

实现:

  1. type Concat<T extends any[], K extends any[]> = [...T, ...K]

xIncludes

在类型系统里实现 JavaScript 的 Array.includes 方法,这个类型接受两个参数,返回的类型要么是 true 要么是 false。例如:

  1. type isPillarMen = Includes<['Kars', 'Esidisi', 'Wamuu', 'Santana'], 'Dio'> // expected to be `false`

Push

在类型系统里实现通用的 Array.push 。例如:

  1. type Result = Push<[1, 2], '3'> // [1, 2, '3']

实现:

  1. type Push<T extends any[], K> = [...T, K]

Unshift

实现类型版本的 Array.unshift。例如:

  1. type Result = Unshift<[1, 2], 0> // [0, 1, 2,]

实现:

  1. type Unshift<T extends any[], K> = [K, ...T]

Parameters

实现内置的 Parameters 类型,而不是直接使用它,Parameters是用来获取一个函数的参数类型的,其中获取的结果是一个元组。例如:

  1. const foo = (arg1: string, arg2: number): void => {}
  2. type FunctionParamsType = MyParameters<typeof foo> // [arg1: string, arg2: number]

实现: