You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为递归返回同结构对象的函数编写TypeScript类型定义?

TypeScript递归处理嵌套对象的类型定义方案

问题场景

需要实现一个可处理任意嵌套对象/数组的递归函数,比如addCssSuffix:

  • 传入数值(或可转为数字的字符串)时,返回带px后缀的字符串,如addCssSuffix(50)返回"50px"
  • 传入嵌套对象/数组时,返回结构完全一致的新对象/数组,其中符合条件的数值都会被加上后缀,如addCssSuffix({width:10, margin:[20, "30"]})返回{width:"10px", margin:["20px", "30px"]}

原TypeScript写法无法精准推断返回类型,比如const i = addCssSuffix(50)会被推断为宽泛类型,而非预期的string。

解决方案:递归条件类型映射

要让TypeScript正确推断输入输出的结构对应关系,需要使用递归条件类型逐个映射输入类型的每个成员:

1. 定义输入到输出的映射类型

先定义泛型类型CssSuffixified<T>,递归处理输入类型T的每个成员:

type CssSuffixified<T> = 
  // 处理数值类型:转为带px的字符串
  T extends number ? `${T}px` :
  // 处理可转为数字的字符串类型:转为带px的字符串
  T extends `${number}` ? `${T}px` :
  // 处理数组:递归映射每个元素
  T extends Array<infer U> ? CssSuffixified<U>[] :
  // 处理对象:递归映射每个属性值
  T extends object ? { [K in keyof T]: CssSuffixified<T[K]> } :
  // 其他类型直接返回原类型
  T;

2. 为函数添加精准类型注解

修改函数,用上述泛型类型约束输入和输出:

function addCssSuffix<T>(input: T, suffix = 'px'): CssSuffixified<T> {
  // 处理数组/对象的递归逻辑
  if (input && typeof input === 'object') {
    if (Array.isArray(input)) {
      return input.map(item => addCssSuffix(item, suffix)) as CssSuffixified<T>;
    }
    return Object.fromEntries(
      Object.entries(input).map(([key, value]) => [
        key, 
        addCssSuffix(value, suffix)
      ])
    ) as CssSuffixified<T>;
  }

  // 处理数值或可转为数字的字符串
  if (typeof input === 'number' || (typeof input === 'string' && !isNaN(Number(input)))) {
    return `${input}${suffix}` as CssSuffixified<T>;
  }

  // 其他类型直接返回
  return input as CssSuffixified<T>;
}

3. 类型推断验证

现在测试场景下,TypeScript能精准推断返回类型:

// 推断i为"50px"字面量类型(本质为string)
const i = addCssSuffix(50);
// 推断obj为{ width: "10px", margin: ["20px", "30px"] }
const obj = addCssSuffix({ width: 10, margin: [20, "30"] });
// 推断str为"100px"
const str = addCssSuffix("100");
// 推断other为boolean(原类型不变)
const other = addCssSuffix(true);

关键说明

  • 递归条件类型CssSuffixified<T>会逐层遍历输入类型的每个成员,确保输出类型和输入结构完全一致
  • 使用as CssSuffixified<T>是因为TypeScript无法自动识别递归函数的返回类型对应关系,手动断言是合理的(类型逻辑已保证正确性)
  • 针对数组和对象分别处理,确保返回的数组/对象结构与输入一致

内容的提问来源于stack exchange,提问作者Kasheftin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 04:55:24