类型体操刷题系列(七)—Chainable/LastOfArray/Pop

401 阅读2分钟

目的

Github上的类型体操,让你写出更加优雅的TS类型定义,以及探寻TS中我们不熟悉的只是,让我们开始TS的类型挑战把~2022希望通过更文的方式来督促自己学习,每日三题,坚持日更不断~~

ts 类型体操 github 我的解答

题目大纲

  1. Medium Chainable Options
  2. Medium Last of array
  3. Medium pop

01. Medium Chainable Options

题目要求

import { Alike, Expect } from '@type-challenges/utils'

declare const a: Chainable

const result = a
  .option('foo', 123)
  .option('bar', { value: 'Hello World' })
  .option('name', 'type-challenges')
  .get()

type cases = [
  Expect<Alike<typeof result, Expected>>
]

type Expected = {
  foo: number
  bar: {
    value: string
  }
  name: string
}

我的答案

type Chainable<T extends object = {}> = {
  option<M extends string, V extends any>(
    key: M,
    value: V
  ): V extends infer P
    ? Chainable<
        {
          [key in M]: P;
        } & T
      >
    : never;
  get(): T;
};

这道题目比较难的一点是需要不断的在 option 执行后的内容类似递归一样能够叠加,所以要如何做到呢~

知识点

  1. 可以增加泛型 + 默认值的方式来扩展字段
  2. 对于函数的参数,如果需要使用infer推断,或者要将string类型转换成 const这个时候可以将参数搞成泛型,这样就可以用推断的方式来进行操作了

2. Medium Last of array

题目要求

import { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Last<[3, 2, 1]>, 1>>,
  Expect<Equal<Last<[() => 123, { a: string }]>, { a: string }>>,
]

我的解答

type Last<T extends any[]> = T extends [...any[], infer P] ? P : undefined;

这个题目比较简单,使用...这个扩展运算符即可

3. Medium pop

题目要求

import { Equal, Expect } from '@type-challenges/utils'

type cases = [
  Expect<Equal<Pop<[3, 2, 1]>, [3, 2]>>,
  Expect<Equal<Pop<['a', 'b', 'c', 'd', ]>, ['a', 'b', 'c']>>,
]

我的解答

type Pop<T extends any[]> = T extends [...infer P, any] ? P : [];

知识点

  1. 如果需要推断数组的类型,比如[1, 2] as const,要直接infer P
  2. 如果想要推断T[number],数组中索引的每一项,这个时候可以使用(infer P)[]