TypeScript 体操,从进阶到放弃!

前言

最近有了面试的打算,所以抽空整理了一些高难度的内容,有兴趣的小伙伴可以跟我一起慢慢过一遍,一定要要自己手写一遍,不会了在来这里参考!

正文

1. If 工具类型
代码语言:javascript代码运行次数:0运行复制
type If<C extends boolean, T, F> = C extends true ? T : F;
代码语言:javascript代码运行次数:0运行复制
type A = If<true, 'yes', 'no'>  // 'yes'
type B = If<false, 1, 2>        // 2
2. Concat:连接两个数组
代码语言:javascript代码运行次数:0运行复制
type Concat<T extends any[], U extends any[]> = [...T, ...U];
代码语言:javascript代码运行次数:0运行复制
type R = Concat<[1, 2], [3, 4]>  // [1, 2, 3, 4]
3. Includes:判断是否包含
代码语言:javascript代码运行次数:0运行复制
type Equal<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? true : false;

typeIncludes<Textendsreadonlyany[], U> = 
Textends [inferF, ...inferR]
    ? Equal<F, U> extendstrue ? true : Includes<R, U>
    : false;
代码语言:javascript代码运行次数:0运行复制
type R = Includes<['a', 'b', 'c'], 'a'>  // true
type R2 = Includes<[1, 2, 3], 4>         // false
4. Push
代码语言:javascript代码运行次数:0运行复制
type Push<T extends any[], U> = [...T, U];
代码语言:javascript代码运行次数:0运行复制
type R = Push<[1, 2], 3>  // [1, 2, 3]
5. Unshift
代码语言:javascript代码运行次数:0运行复制
type Unshift<T extends any[], U> = [U, ...T];
代码语言:javascript代码运行次数:0运行复制
type R = Unshift<[2, 3], 1>  // [1, 2, 3]
6. Length
代码语言:javascript代码运行次数:0运行复制
type Length<T extends readonly any[]> = T['length'];
代码语言:javascript代码运行次数:0运行复制
type R = Length<[1, 2, 3]>  // 3
7. Pop
代码语言:javascript代码运行次数:0运行复制
type Pop<T extends any[]> = T extends [...infer R, any] ? R : never;
代码语言:javascript代码运行次数:0运行复制
type R = Pop<[1, 2, 3]>  // [1, 2]
8. Shift
代码语言:javascript代码运行次数:0运行复制
type Shift<T extends any[]> = T extends [any, ...infer R] ? R : never;
代码语言:javascript代码运行次数:0运行复制
type R = Shift<[1, 2, 3]>  // [2, 3]
9. TupleToUnion
代码语言:javascript代码运行次数:0运行复制
type TupleToUnion<T extends any[]> = T[number];
代码语言:javascript代码运行次数:0运行复制
type R = TupleToUnion<['a', 'b', 'c']>  // 'a' | 'b' | 'c'
10. Last
代码语言:javascript代码运行次数:0运行复制
type Last<T extends any[]> = T extends [...any[], infer L] ? L : never;
代码语言:javascript代码运行次数:0运行复制
type R = Last<[1, 2, 3]>  // 3
11. Append
代码语言:javascript代码运行次数:0运行复制
type Append<T extends any[], U> = [...T, U];
代码语言:javascript代码运行次数:0运行复制
type R = Append<[1, 2], 3>  // [1, 2, 3]
12. StartsWith
代码语言:javascript代码运行次数:0运行复制
type StartsWith<S extends string, P extends string> = 
  S extends `${P}${string}` ? true : false;
代码语言:javascript代码运行次数:0运行复制
type R = StartsWith<'typescript', 'type'>  // true
13. TrimLeft
代码语言:javascript代码运行次数:0运行复制
type TrimLeft<S extends string> = S extends ` ${infer R}` ? TrimLeft<R> : S;
代码语言:javascript代码运行次数:0运行复制
type R = TrimLeft<'   hello'>  // 'hello'
14. TrimRight
代码语言:javascript代码运行次数:0运行复制
type TrimRight<S extends string> = S extends `${infer R} ` ? TrimRight<R> : S;
代码语言:javascript代码运行次数:0运行复制
type R = TrimRight<'hello   '>  // 'hello'
15. Trim
代码语言:javascript代码运行次数:0运行复制
type Trim<S extends string> = TrimLeft<TrimRight<S>>;
代码语言:javascript代码运行次数:0运行复制
type R = Trim<'   hello   '>  // 'hello'
16. Replace
代码语言:javascript代码运行次数:0运行复制
type Replace<S extends string, From extends string, To extends string> = 
  S extends `${infer L}${From}${infer R}` ? `${L}${To}${R}` : S;
代码语言:javascript代码运行次数:0运行复制
type R = Replace<'hello world', 'world', 'TS'>  // 'hello TS'
17. ReplaceAll
代码语言:javascript代码运行次数:0运行复制
type ReplaceAll<S extends string, From extends string, To extends string> = 
  S extends `${infer L}${From}${infer R}` ? ReplaceAll<`${L}${To}${R}`, From, To> : S;
代码语言:javascript代码运行次数:0运行复制
type R = ReplaceAll<'a_a_a', '_', '-'>  // 'a-a-a'
18. CapitalizeWords
代码语言:javascript代码运行次数:0运行复制
type CapitalizeWords<S extends string> =
  S extends `${infer Head} ${infer Tail}`
    ? `${Capitalize<Head>} ${CapitalizeWords<Tail>}`
    : Capitalize<S>;
代码语言:javascript代码运行次数:0运行复制
type R = CapitalizeWords<'hello world ts'>  // 'Hello World Ts'
19. ReverseTuple
代码语言:javascript代码运行次数:0运行复制
type Reverse<T extends any[], R extends any[] = []> = 
  T extends [infer F, ...infer Rest] ? Reverse<Rest, [F, ...R]> : R;
代码语言:javascript代码运行次数:0运行复制
type R = Reverse<[1, 2, 3]>  // [3, 2, 1]
20. Flatten
代码语言:javascript代码运行次数:0运行复制
type Flatten<T extends any[]> = 
  T extends [infer F, ...infer R]
    ? [...(F extends any[] ? Flatten<F> : [F]), ...Flatten<R>]
    : [];
代码语言:javascript代码运行次数:0运行复制
type R = Flatten<[1, [2, 3], [[4]]]>  // [1, 2, 3, 4]
21. DeepReadonly
代码语言:javascript代码运行次数:0运行复制
type DeepReadonly<T> = {
  readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
代码语言:javascript代码运行次数:0运行复制
type Obj = { a: { b: { c: string } } };
type R = DeepReadonly<Obj>;
// { readonly a: { readonly b: { readonly c: string } } }
22. UnionToIntersection
代码语言:javascript代码运行次数:0运行复制
type UnionToIntersection<U> = 
  (U extends any ? (k: U) => void : never) extends 
  (k: infer I) => void ? I : never;
代码语言:javascript代码运行次数:0运行复制
type R = UnionToIntersection<{a: 1} | {b: 2}>  // {a: 1} & {b: 2}
23. Permutation
代码语言:javascript代码运行次数:0运行复制
type Permutation<T, K = T> =
  [T] extends [never] ? [] :
  T extends K ? [T, ...Permutation<Exclude<K, T>>] : never;
代码语言:javascript代码运行次数:0运行复制
type R = Permutation<'a' | 'b' | 'c'>
// ['a','b','c'] | ['a','c','b'] | ['b','a','c'] | ...
24. IsUnion
代码语言:javascript代码运行次数:0运行复制
type IsUnion<T, C = T> = 
  T extends any ? ([C] extends [T] ? false : true) : never;
代码语言:javascript代码运行次数:0运行复制
type R1 = IsUnion<string | number>  // true
type R2 = IsUnion<string>           // false
25. IsNever
代码语言:javascript代码运行次数:0运行复制
type IsNever<T> = [T] extends [never] ? true : false;
代码语言:javascript代码运行次数:0运行复制
type R1 = IsNever<never>  // true
type R2 = IsNever<string> // false
26. IsTuple
代码语言:javascript代码运行次数:0运行复制
type IsTuple<T> = 
  T extends readonly any[] ? number extends T['length'] ? false : true : false;
代码语言:javascript代码运行次数:0运行复制
type R1 = IsTuple<[1, 2]>    // true
type R2 = IsTuple<number[]>  // false
27. Get<T, K> 类似 lodash.get
代码语言:javascript代码运行次数:0运行复制
type Get<T, K extends string> = 
  K extends `${infer F}.${infer R}`
    ? F extends keyof T ? Get<T[F], R> : never
    : K extends keyof T ? T[K] : never;
代码语言:javascript代码运行次数:0运行复制
type Obj = { a: { b: { c: string } } };
type R = Get<Obj, 'a.b.c'>  // string
28. PickByValue
代码语言:javascript代码运行次数:0运行复制
type PickByValue<T, V> = {
  [K in keyof T as T[K] extends V ? K : never]: T[K];
};
代码语言:javascript代码运行次数:0运行复制
type Obj = { name: string; age: number; gender: string };
type R = PickByValue<Obj, string>  // { name: string; gender: string }

最后

我也是边学边实现的,如果有啥错误的地方欢迎指正!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-04-28,如有侵权请联系 cloudcommunity@tencent 删除面试typescriptextendsstring工具类