MST

星途 面试题库

面试题:TypeScript条件类型之递归与条件类型结合

实现一个复杂的TypeScript条件类型 `DeepReadonly<T>`,它可以将一个复杂对象(对象中可能嵌套对象和数组)变为只读类型。例如,输入 `{ a: { b: 1 } }`,输出应为 `{ readonly a: { readonly b: 1 } }`。要求必须使用递归和条件类型来实现,详细说明实现思路和每一步的作用。
27.7万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 首先,定义一个基础的条件类型来处理对象类型。
  2. 使用 keyof 操作符获取对象的所有键。
  3. 通过 in 关键字进行遍历,为每个键创建只读属性。
  4. 对于属性值,如果它是对象类型,则递归调用 DeepReadonly 来处理嵌套对象。
  5. 如果属性值是数组类型,同样递归处理数组元素。

代码实现

type DeepReadonly<T> =
  T extends Array<infer U>
  ? ReadonlyArray<DeepReadonly<U>>
   : T extends object
    ? {
        readonly [P in keyof T]: DeepReadonly<T[P]>;
      }
    : T;

每一步解释

  1. 数组处理
    T extends Array<infer U>
    

? ReadonlyArray<DeepReadonly>

- `T extends Array<infer U>` 检查 `T` 是否为数组类型,如果是,则推断出数组元素类型 `U`。
- `ReadonlyArray<DeepReadonly<U>>` 创建一个只读数组,数组元素类型是递归处理后的 `U`。

2. **对象处理**:
```typescript
T extends object
 ? {
     readonly [P in keyof T]: DeepReadonly<T[P]>;
   }
  • T extends object 检查 T 是否为对象类型。
  • keyof T 获取对象 T 的所有键。
  • [P in keyof T] 遍历对象的所有键 P
  • readonly [P in keyof T]: DeepReadonly<T[P]> 为每个键 P 创建一个只读属性,属性值是递归处理后的 T[P]
  1. 其他类型处理
     : T;
    
    如果 T 既不是数组也不是对象,则直接返回 T,保持原类型不变。