类型体操刷题系列(二十三)— Fill/TrimRight/Without

426 阅读1分钟

目的

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

题目大纲

  1. Medium Fill
  2. Medium Trim Right
  3. Medium Without

01. Medium Fill

题目要求

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

type cases = [
  Expect<Equal<Fill<[], 0>, []>>,
  Expect<Equal<Fill<[], 0, 0, 3>, []>>,
  Expect<Equal<Fill<[1, 2, 3], 0, 0, 0>, [1, 2, 3]>>,
  Expect<Equal<Fill<[1, 2, 3], 0, 2, 2>, [1, 2, 3]>>,
  Expect<Equal<Fill<[1, 2, 3], 0>, [0, 0, 0]>>,
  Expect<Equal<Fill<[1, 2, 3], true>, [true, true, true]>>,
  Expect<Equal<Fill<[1, 2, 3], true, 0, 1>, [true, 2, 3]>>,
  Expect<Equal<Fill<[1, 2, 3], true, 1, 3>, [1, true, true]>>,
  Expect<Equal<Fill<[1, 2, 3], true, 10, 0>, [1, 2, 3]>>,
  Expect<Equal<Fill<[1, 2, 3], true, 0, 10>, [true, true, true]>>,
]

我的答案

type Slice<
  T extends any[],
  Start extends number = 0,
  End extends number = T["length"],
  R extends any[] = [],
  Count extends any[] = []
> = Count["length"] extends T["length"]
  ? R
  : Count["length"] extends End
  ? R
  : Count["length"] extends Start
  ? Slice<T, Start, End, [...R, T[Start]], [...Count, number]>
  : R extends []
  ? Slice<T, Start, End, R, [...Count, number]>
  : Slice<T, Start, End, [...R, T[Count["length"]]], [...Count, number]>;

type FillArray<
  N,
  Start extends number,
  End extends number,
  MaxLength extends number,
  R extends any[] = [],
  Count extends any[] = []
> = Count["length"] extends MaxLength
  ? R
  : Count["length"] extends End
  ? R
  : Count["length"] extends Start
  ? FillArray<N, Start, End, MaxLength, [N], [...Count, number]>
  : R["length"] extends 0
  ? FillArray<N, Start, End, MaxLength, R, [...Count, number]>
  : FillArray<N, Start, End, MaxLength, [...R, N], [...Count, number]>;

type Fill<
  T extends unknown[],
  N,
  Start extends number = 0,
  End extends number = T["length"],
  StartArray extends any[] = Slice<T, 0, Start>,
  EndArray extends any[] = Slice<T, End, T["length"]>,
  R extends any[] = FillArray<N, Start, End, T["length"]>
> = GreaterThan<Start, End> extends true
  ? T
  : T extends []
  ? []
  : [...StartArray, ...R, ...EndArray];

知识点

  1. 这是个综合的题目通过Slice + Array Fill拆解成两个递归来完成这个功能

  2. 通过之前的GreaterThan来做边界的判断

2. Medium TrimRight

题目要求

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

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

我的解答

type EmptyLetter = " " | "\n" | "\t";

type TrimRight<S extends string> = S extends `${infer P}${EmptyLetter}`
  ? TrimRight<P>
  : S;

知识点

  1. 之前在Trim中已经介绍过,主要就是拼接字符串的extends判断

3. Medium Without

题目要求

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

type cases = [
  Expect<Equal<Without<[1, 2], 1>, [2]>>,
  Expect<Equal<Without<[1, 2, 4, 1, 5], [1, 2]>, [4, 5]>>,
  Expect<Equal<Without<[2, 3, 2, 3, 2, 3, 2, 3], [2, 3]>, []>>
]

我的解答

type FormatArray<T> = T extends any[] ? T : [T];

type Without<
  T extends any[],
  U,
  R extends any[] = [],
  K extends any[] = FormatArray<U>
> = T extends [infer P, ...infer C]
  ? Includes<K, P> extends true
    ? Without<C, U, R>
    : Without<C, U, [...R, P]>
  : R;

知识点

  • 简单的递归 + 对于数组infer拆分的判断