Skip to content

TS体操练习

✨文章摘要(AI生成)

本文记录了 TypeScript 类型体操练习题的解答过程,包括简单和中等难度的多个练习题。涵盖了 Pick、Readonly、TupleToObject、Exclude、Awaited 等类型实现,并对 infer、协变和逆变等重要概念进行了说明。这些练习有助于加深对 TypeScript 类型系统的理解,提升类型编程能力。

题目链接如下

type-challenges/README.zh-CN.md at main · type-challenges/type-challenges (github.com)

简单

4. 实现pick

ts
type MyPick<T, K extends keyof T> = {
  [P in K]: T[P]
}

7. 对象属性只读

ts
type MyReadonly<T> = {
 readonly [P in keyof T]: T[P]
}

11. 元组转换为对象

  • T[number] 可以去遍历联合类型
ts
type TupleToObject<T extends readonly PropertyKey[]> = {
  [P in T[number]]: P
}

14. 第一个元素

ts
type First<T extends any[]> = T extends [] ? never : T[0]

18. 获取元组长度

  • 利用类数组元素的length属性
ts
type Length<T extends readonly PropertyKey[]> = T['length']

43. 实现 Exclude

ts
// T中的某一项如果在U中(T extends U),返回never移除U,否则返回T。
type MyExclude<T, U> = T extends U ? never : T;

189. Awaited

ts
// 思路:
// 1. infer U - 反向获取到泛型的入参类型
// 2. 对于嵌套Promise的情况做递归调用处理,通过U extends PromiseLike<any>,判断是否为Promise
type MyAwaited<T extends PromiseLike<any>> = T extends PromiseLike<infer U> ? U extends PromiseLike<any> ? MyAwaited<U> : U : never

infer:

infer作用:推导泛型参数

ts
// infer 例子
type numberPromise = Promise<number>;
type n = numberPromise extends Promise<infer P> ? P : never; // number

268. If

ts
type If<C extends boolean, T, F> = C extends true ? T : F

533. Concat

ts
type Tuple = readonly unknown[];
type Concat<T extends Tuple, U extends Tuple> = [...T, ...U]

898. Includes

这题很难,做个标记

主要是通过T extends [infer First, ...infer Rest],每次校验arr的第一位,看是否等于U,以此递归

ts
type Includes<T extends readonly unknown[], U> =
  T extends [infer First, ...infer Rest]
    ? Equal<First, U> extends true ? true : Includes<Rest, U>
    : false;

3057. Push

ts
type Push<T extends unknown[], U> = [...T, U]

3060. Unshift

ts
type Unshift<T extends unknown[], U> = [U, ...T];

3312. Parameters

这个重点是掌握参数结构,也是通过infer去获取入参的类型

ts
type MyParameters<T extends (...args: any[]) => any> =  T extends (...args: infer S) => void ? S : any

中等

2. 获取函数返回类型

ts
type MyReturnType<T extends Function> = T extends (...args: any) =>  infer R ? R : never

3. 实现 Omit

ts
// 如果没有 as 关键字,键将被解释为普通属性键,并且基于 P extends K 的条件类型排除将无法按预期工作
// 因此它的主要目标是映射索引签名的键
type MyOmit<T, K extends keyof T> = {
  [P in keyof T as P extends K ? never : P]: T[P]
}

8. 对象部分属性只读

知识点

协变和逆变

  • 协变:类型推导到其子类型的过程,A | B -> A & B 就是一个协变

  • 逆变:类型推导到其超类型的过程

参考

Last updated: