类型体操刷题系列(十)— LengthOfString/Flatten/AppendToObject

467 阅读2分钟

目的

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

ts 类型体操 github 我的解答

题目大纲

  1. Medium Length Of String
  2. Medium Flatten
  3. Medium Permutation

01. Length Of String

题目要求

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

type cases = [
  Expect<Equal<LengthOfString<''>, 0>>,
  Expect<Equal<LengthOfString<'kumiko'>, 6>>,
  Expect<Equal<LengthOfString<'reina'>, 5>>,
  Expect<Equal<LengthOfString<'Sound! Euphonium'>, 16>>,
]

我的答案

type LengthOfString<
  S extends string,
  C extends any[] = []
> = S extends `${infer P}${infer T}`
  ? LengthOfString<T, [...C, P]>
  : GetLength<C>;

type GetLength<T extends readonly any[]> = T["length"];

知识点

  1. 使用readonly any[]得 length 方法可以获得对应数组得长度
  2. 所以这个递归得表达式,就是弄一个空数组不停得把第一个字符放进去,最后从字符串变成了readonly得数组就可以获得他得长度了

2. Medium Flatten

题目要求

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

type cases = [
  Expect<Equal<Flatten<[]>, []>>,
  Expect<Equal<Flatten<[1, 2, 3, 4]>, [1, 2, 3, 4]>>,
  Expect<Equal<Flatten<[1, [2]]>, [1, 2]>>,
  Expect<Equal<Flatten<[1, 2, [3, 4], [[[5]]]]>, [1, 2, 3, 4, 5]>>,
  Expect<Equal<Flatten<[{foo: 'bar'; 2: 10}, 'foobar']>, [{foo: 'bar'; 2: 10}, 'foobar']>>,
]

我的解答

type Flatten<P extends any[], R extends any[] = []> = P extends [
  infer First,
  ...infer P
]
  ? First extends any[]
    ? [...R, ...Flatten<First>, ...Flatten<P>]
    : [...R, First, ...Flatten<P>]
  : [];

知识点

  1. 没有条件创造条件,当前数组是多层得直接用 flatten 递归就行
  2. 创造一个空的泛型作为结果接收对应得数组内容即可

3. Medium Permutation

题目要求

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

type test1 = {
  key: 'cat'
  value: 'green'
}

type testExpect1 = {
  key: 'cat'
  value: 'green'
  home: boolean
}

type test2 = {
  key: 'dog' | undefined
  value: 'white'
  sun: true
}

type testExpect2 = {
  key: 'dog' | undefined
  value: 'white'
  sun: true
  home: 1
}

type test3 = {
  key: 'cow'
  value: 'yellow'
  sun: false
}

type testExpect3 = {
  key: 'cow'
  value: 'yellow'
  sun: false
  isMotherRussia: false | undefined
}

type cases = [
  Expect<Equal<AppendToObject<test1, 'home', boolean>, testExpect1>>,
  Expect<Equal<AppendToObject<test2, 'home', 1>, testExpect2>>,
  Expect<Equal<AppendToObject<test3, 'isMotherRussia', false | undefined>, testExpect3>>,
]

我的解答

type AppendToObject<
  T extends object,
  U extends string,
  V,
  R extends T = T & { [key in U]: V }
> = {
  [K in keyof R]: R[K];
};

知识点

  1. 需要将两个对象合并之后,用对象遍历得方式输出一个新得对象。
  2. 如果直接 A & B这种写法好像用例过不了