MST

星途 面试题库

面试题:TypeScript泛型函数在复杂数据结构组合操作中的应用

假设有一个复杂数据结构,它是一个包含多个嵌套数组和对象的结构,例如{ data: [[{ value: 1 }, { value: 2 }], [{ value: 3 }]] }。编写一个TypeScript泛型函数,能够深入遍历这个复杂结构,对所有符合特定类型(通过泛型约束)的值进行操作(操作由回调函数定义),并返回操作后的整个复杂结构。要详细处理好各种嵌套情况,确保类型系统在整个过程中能准确无误地工作,同时要考虑性能优化。
13.7万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试
type DeepReadonly<T> = T extends Function
  ? T
  : T extends Array<infer U>
  ? DeepReadonlyArray<U>
  : T extends object
  ? DeepReadonlyObject<T>
  : T;

interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}

interface DeepReadonlyObject<T> {
  readonly [P in keyof T]: DeepReadonly<T[P]>;
}

function deepTraverseAndTransform<T, U extends keyof T, V>(
  data: DeepReadonly<T>,
  typeKey: U,
  callback: (value: T[U]) => V
): T {
  return JSON.parse(
    JSON.stringify(data),
    (key, value) => {
      if (key === typeKey) {
        return callback(value);
      }
      return value;
    }
  ) as T;
}

// 示例用法
const complexData = {
  data: [[{ value: 1 }, { value: 2 }], [{ value: 3 }]]
};

const newComplexData = deepTraverseAndTransform(
  complexData,
  'value',
  (value) => value * 2
);

console.log(newComplexData);

代码解释

  1. 类型定义
    • DeepReadonly 是一个递归类型别名,用于将任何嵌套的数组或对象转换为只读类型,以确保在遍历过程中不会意外修改原始数据结构。
    • DeepReadonlyArrayDeepReadonlyObject 是辅助类型,用于更清晰地定义数组和对象的只读结构。
  2. deepTraverseAndTransform 函数
    • 接收三个参数:
      • data:要遍历的复杂数据结构,类型为 DeepReadonly<T>,确保数据结构只读。
      • typeKey:用于指定要操作的值的键名,类型为 U extends keyof T,确保键名在数据结构中存在。
      • callback:用于定义对符合特定类型的值进行操作的回调函数,类型为 (value: T[U]) => V,返回操作后的值。
    • 使用 JSON.stringifyJSON.parse 结合 replacer 函数来遍历和转换数据。replacer 函数在遇到指定的 typeKey 时,调用 callback 对值进行操作,其他情况下返回原始值。最后将解析后的结果转换回 T 类型。
  3. 示例用法
    • 定义了一个 complexData 作为示例数据结构。
    • 调用 deepTraverseAndTransform 函数,对 value 键对应的值进行乘以2的操作,并输出结果。

性能优化

  1. 避免深度递归:使用 JSON.stringifyJSON.parse 避免了手动深度递归遍历,减少了栈溢出的风险,并且在处理复杂嵌套结构时性能相对稳定。
  2. 只读类型:通过 DeepReadonly 类型确保原始数据不会被意外修改,减少潜在的错误,从整体上提升程序性能和稳定性。