类型体操刷题系列(七)—PromiseAll/LookUp/TrimLeft

241 阅读2分钟

目的

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

ts 类型体操 github 我的解答

题目大纲

  1. Medium Promise All
  2. Medium Look Up
  3. Medium Trim Left

01. Medium Promise All

题目要求

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

const promiseAllTest1 = PromiseAll([1, 2, 3] as const)
const promiseAllTest2 = PromiseAll([1, 2, Promise.resolve(3)] as const)
const promiseAllTest3 = PromiseAll([1, 2, Promise.resolve(3)])

type cases = [
  Expect<Equal<typeof promiseAllTest1, Promise<[1, 2, 3]>>>,
  Expect<Equal<typeof promiseAllTest2, Promise<[1, 2, number]>>>,
  Expect<Equal<typeof promiseAllTest3, Promise<[number, number, number]>>>
]

我的答案

declare function PromiseAll<T extends any[] = any[]>(
  values: readonly [...T]
): Promise<{ [K in keyof T]: T[K] extends Promise<infer R> ? R : T[K] }>;

知识点

  1. 关键是values是readonly [...T],如果是readonly修饰的这样就可以通过...T推断出相关的类型,这个地方就是个联合类型了

  2. 将一个any[]转换为一个const在 typescript 类型中的操作为增加 readOnly,就可以将范围缩小

  3. 当一个数组readonly的时候,意味着他的顺序是一定的,这个时候也可以使用遍历对象的 mapped 去遍历数组

2. Medium Look Up

题目要求

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

interface Cat {
  type: 'cat'
  breeds: 'Abyssinian' | 'Shorthair' | 'Curl' | 'Bengal'
}

interface Dog {
  type: 'dog'
  breeds: 'Hound' | 'Brittany' | 'Bulldog' | 'Boxer'
  color: 'brown' | 'white' | 'black'
}

type Animal = Cat | Dog

type cases = [
  Expect<Equal<LookUp<Animal, 'dog'>, Dog>>,
  Expect<Equal<LookUp<Animal, 'cat'>, Cat>>,
]

我的解答

type LookUp<U extends { type: any }, T> = U extends infer P
  ? P extends { type: any }
    ? T extends P["type"]
      ? P
      : never
    : never
  : never;

知识点:

  1. 构造一个两个对象的基类,然后用infer对关键的字段进行判断即可

3. Medium Trim Left

题目要求

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

type cases = [
  Expect<Equal<TrimLeft<'str'>, 'str'>>,
  Expect<Equal<TrimLeft<' str'>, 'str'>>,
  Expect<Equal<TrimLeft<'     str'>, 'str'>>,
  Expect<Equal<TrimLeft<'     str     '>, 'str     '>>,
  Expect<Equal<TrimLeft<'   \n\t foo bar '>, 'foo bar '>>,
]

我的解答

type TrimLeft<T extends string> = T extends `${infer P}${infer K}`
  ? P extends " " | "\n" | "\t"
    ? TrimLeft<K>
    : T
  : never;

知识点

  1. TS的递归方式
  2. 联合类型的判断,也可以通过extends,学名叫分布式类型判断