Trim Left

  • 实现 TrimLeft ,它接收确定的字符串类型并返回一个新的字符串,其中新返回的字符串删除了原字符串开头的空白字符串。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    type TrimLeft<S extends string> = S extends `${" " | "\n" | "\t"}${infer R}` ? TrimLeft<R> : S

    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 '>>,
    Expect<Equal<TrimLeft<''>, ''>>,
    Expect<Equal<TrimLeft<' \n\t'>, ''>>,
    ]

Trim

  • 实现Trim,它是一个字符串类型,并返回一个新字符串,其中两端的空白符都已被删除。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    type Trim<S extends string> = S extends `${" " | "\n" | "\t"}${infer R}` | `${infer R}${" " | "\n" | "\t"}` ? Trim<R> : S

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

Capitalize

  • 实现 Capitalize 它将字符串的第一个字母转换为大写,其余字母保持原样。
    1
    2
    3
    4
    5
    6
    7
    8
    type MyCapitalize<S extends string> = S extends `${infer First}${infer Rest}` ? `${Uppercase<First>}${Rest}` : S

    Expect<Equal<MyCapitalize<'foobar'>, 'Foobar'>>,
    Expect<Equal<MyCapitalize<'FOOBAR'>, 'FOOBAR'>>,
    Expect<Equal<MyCapitalize<'foo bar'>, 'Foo bar'>>,
    Expect<Equal<MyCapitalize<''>, ''>>,
    Expect<Equal<MyCapitalize<'a'>, 'A'>>,
    Expect<Equal<MyCapitalize<'b'>, 'B'>>,

Replace

  • 实现 Replace<S, From, To> 将字符串 S 中的第一个子字符串 From 替换为 To 。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    type Replace<S extends string, From extends string, To extends string> = S extends `${infer A}${From}${infer B}` ? From extends '' ? S :`${A}${To}${B}` : S

    type cases = [
    Expect<Equal<Replace<'foobar', 'bar', 'foo'>, 'foofoo'>>,
    Expect<Equal<Replace<'foobarbar', 'bar', 'foo'>, 'foofoobar'>>,
    Expect<Equal<Replace<'foobarbar', '', 'foo'>, 'foobarbar'>>,
    Expect<Equal<Replace<'foobarbar', 'bar', ''>, 'foobar'>>,
    Expect<Equal<Replace<'foobarbar', 'bra', 'foo'>, 'foobarbar'>>,
    Expect<Equal<Replace<'', '', ''>, ''>>,
    ]

ReplaceAll

  • 实现 ReplaceAll<S, From, To> 将一个字符串 S 中的所有子字符串 From 替换为 To。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    type ReplaceAll<S extends string, From extends string, To extends string> = S extends `${infer A}${From}${infer B}` ? From extends '' ? S :  `${A}${To}${ReplaceAll<B, From, To>}` : S

    type cases = [
    Expect<Equal<ReplaceAll<'foobar', 'bar', 'foo'>, 'foofoo'>>,
    Expect<Equal<ReplaceAll<'foobar', 'bag', 'foo'>, 'foobar'>>,
    Expect<Equal<ReplaceAll<'foobarbar', 'bar', 'foo'>, 'foofoofoo'>>,
    Expect<Equal<ReplaceAll<'t y p e s', ' ', ''>, 'types'>>,
    Expect<Equal<ReplaceAll<'foobarbar', '', 'foo'>, 'foobarbar'>>,
    Expect<Equal<ReplaceAll<'barfoo', 'bar', 'foo'>, 'foofoo'>>,
    Expect<Equal<ReplaceAll<'foobarfoobar', 'ob', 'b'>, 'fobarfobar'>>,
    Expect<Equal<ReplaceAll<'foboorfoboar', 'bo', 'b'>, 'foborfobar'>>,
    Expect<Equal<ReplaceAll<'', '', ''>, ''>>,
    ]

Append Argument

  • 实现一个泛型 AppendArgument<Fn, A>,对于给定的函数类型 Fn,以及一个任意类型 A,返回一个新的函数 G。G 拥有 Fn 的所有参数并在末尾追加类型为 A 的参数。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    type AppendArgument<Fn extends Function, A extends unknown> = Fn extends (...args: infer T) => infer U
    ? (...args: [...T, A]) => U
    : Fn


    type Case1 = AppendArgument<(a: number, b: string) => number, boolean>
    type Result1 = (a: number, b: string, x: boolean) => number

    type Case2 = AppendArgument<() => void, undefined>
    type Result2 = (x: undefined) => void

    type cases = [
    Expect<Equal<Case1, Result1>>,
    Expect<Equal<Case2, Result2>>,
    // @ts-expect-error
    AppendArgument<unknown, undefined>,
    ]

Permutation

  • 实现联合类型的全排列,将联合类型转换成所有可能的全排列数组的联合类型。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    type Permutation<T, Acc = T> = [T] extends [never]
    ? []
    : Acc extends T
    ? [Acc, ...Permutation<Exclude<T, Acc>>]
    : []

    type cases = [
    Expect<Equal<Permutation<'A'>, ['A']>>,
    Expect<Equal<Permutation<'A' | 'B' | 'C'>, ['A', 'B', 'C'] | ['A', 'C', 'B'] | ['B', 'A', 'C'] | ['B', 'C', 'A'] | ['C', 'A', 'B'] | ['C', 'B', 'A']>>,
    Expect<Equal<Permutation<'B' | 'A' | 'C'>, ['A', 'B', 'C'] | ['A', 'C', 'B'] | ['B', 'A', 'C'] | ['B', 'C', 'A'] | ['C', 'A', 'B'] | ['C', 'B', 'A']>>,
    Expect<Equal<Permutation<boolean>, [false, true] | [true, false]>>,
    Expect<Equal<Permutation<never>, []>>,
    ]

Length of String

  • 计算字符串的长度,类似于 String#length
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    type 
    type LengthOfString<S extends string, Acc extends string[] = []
    > = S extends `${infer Head}${infer Tail}`
    ? LengthOfString<Tail, [...Acc, Head]> : Acc['length']

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

Flatten

  • 写一个接受数组的类型,并且返回扁平化的数组类型
    1
    2
    3
    4
    5
    6
    7
    8
    9
    type Flatten<T extends any[]> = T extends [infer F, ... infer R] ? F extends unknown[] ? [...Flatten<F>, ...Flatten<R>] : [F, ...Flatten<R>] : []

    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']>>,
    ]

Append to object

  • 实现一个为接口添加一个新字段的类型。该类型接收三个参数,返回带有新字段的接口类型。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    type AppendToObject<T extends Object, U extends PropertyKey, V> = { [key in (keyof T | U)]: key extends keyof T ? T[key] : V }

    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>>,
    ]