实现DeeepReadonly

108 阅读1分钟

题目描述 🎯

实现一个通用的DeeepReadonly<T>类型,他将对象的每个参数及其子对象递归的设置为只读。

题目分析 📝

type X = {
  x: {
    a: number
    b: string
  }
  y: string
}

type Expercted = {
  readonly x: {
    readonly a: number
    readonly b: string
  }
  readonly y: string
}

需要考虑的问题:

  1. 处理对象的每个属性。
  2. 递归处理嵌套对象。
  3. 为每层级的属性添加readonly修饰符。

解题思路 💡

  1. 使用映射类型遍历对象的所有属性。
  2. 为每个属性添加readonly修饰符。
  3. 对属性值进行判断:
  • 如果是对象类型,递归应用DeepReadonly
  • 如果是基本类型,直接使用原类型。

代码实现 ⌨️

type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]
}

题解详解 🔍

  1. 映射类型部分
[P in keyof T]
  • 遍历对象T的所有属性。
  1. readonly修饰符
readonly [P in keyof T]
  • 为每个属性添加readonly修饰符。
  1. 条件类型判断
T[P] extends object ? DeepReadonly<T[P]> : T[P]
  • 如果属性值是对象,递归应用DeepReadonly
  • 如果不是对象,保持原类型。

示例分析 🌟

interface Example {
  name: string;
  info: {
    age: number;
    address: {
      city: string;
    }
  }
}

type Result = DeepReadonly<Example>;

// 执行过程:

// 第一层
{
  readonly name: string;  // 基本类型,直接加 readonly
  readonly info: {        // 对象类型,递归处理
    readonly age: number;
    readonly address: {   // 继续递归处理
      readonly city: string;
    }
  }
}

// 详细步骤:
// 1. 处理name属性,name 是 string 类型,直接添加 readonly 修饰符。
readonly name: string;

// 2. 处理 info 属性,info 是一个对象类型,递归处理。
readonly info: DeepReadonly<{
  age: number;
  address: {
    city: string;
  }
}>

// 3. 递归处理 info 内部
readonly info: {
  readonly age: number; // age 是基本类型
  readonly address: DeepReadonly<{
    city: string;
  }>
}

// 最终结果
readonly name: string;
readonly info: {
    readonly age: number;
    readonly address: {
      readonly city: string;
    }
}