MST

星途 面试题库

面试题:TypeScript 函数式构造下的泛型类型流转优化及性能考量

在大型项目中,有一个通用的类型转换需求:将任意深度嵌套的对象类型中的所有字符串数组 `string[]` 转换为数字数组 `number[]`,数字为原字符串的长度。使用 TypeScript 的函数式构造和泛型来设计一个高效、可复用的解决方案。同时,阐述在实现过程中如何考虑性能问题,以及如何避免潜在的类型爆炸问题。
21.6万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

实现代码

type DeepTransform<T> = T extends string[]
  ? number[]
  : T extends Array<infer U>
    ? Array<DeepTransform<U>>
    : T extends object
      ? {
          [K in keyof T]: DeepTransform<T[K]>;
        }
      : T;

function deepTransform<T>(obj: T): DeepTransform<T> {
  if (Array.isArray(obj)) {
    if (obj.length === 0 || typeof obj[0] === 'string') {
      return obj.map(str => (typeof str === 'string' ? str.length : 0)) as DeepTransform<T>;
    } else {
      return obj.map(item => deepTransform(item)) as DeepTransform<T>;
    }
  } else if (typeof obj === 'object' && obj!== null) {
    const result: any = {};
    for (const key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        result[key] = deepTransform(obj[key]);
      }
    }
    return result;
  }
  return obj;
}

性能考虑

  1. 减少递归深度:在 deepTransform 函数中,对于数组类型,首先判断其元素是否为字符串。如果是,则直接进行转换,避免不必要的递归。这样可以减少递归调用栈的深度,提高性能。
  2. 缓存结果:对于一些重复出现的子结构,可以考虑使用缓存机制。不过在这种通用的类型转换场景中,由于对象结构的多样性,缓存实现较为复杂且收益不一定高,这里暂未实现。

避免类型爆炸

  1. 限制泛型深度:在定义 DeepTransform 类型时,虽然没有明确限制泛型递归的深度,但通过 if - else 逻辑在运行时避免了无限递归。例如,对于非对象和非数组类型直接返回原类型,避免了进一步的类型扩展。
  2. 避免过度嵌套泛型:在设计类型转换逻辑时,尽量使用简单的泛型嵌套结构。例如,只在对象和数组类型上进行递归,而不是在更多复杂的类型组合上嵌套泛型,这样可以减少类型计算的复杂度,避免类型爆炸。