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

如何递归替换TypeScript中函数、数组等类型的指定类型?

递归替换TypeScript嵌套类型中的指定类型(支持函数、数组、元组、泛型容器)

需求说明

之前的类型替换方案无法覆盖所有场景,需要实现一个能递归处理嵌套结构的类型工具:

  • 替换函数的参数和返回值中的指定类型
  • 保留数组、元组的结构特性,替换其元素类型
  • 支持Promise、Set、Map这类泛型容器的内部类型替换
  • 递归处理对象的嵌套属性

测试用例

type Foo = {
    bar(x: number, y: string): string
    baz: {
        a(): string
        b: [string, string]
        c: string[]
    },
    bing: Promise<string>
    boom: Set<string>
    bah: {
        a: Map<number, string>
        b: Map<string, string>
        c: Map<string, number>
    }
};

type Bar = ReplaceTypes<Foo, string, "inky" | "pinky" | "blinky" | "clyde">;

var x: Bar;

预期输出

var x: {
    bar: (x: number, y: "inky" | "pinky" | "blinky" | "clyde") => "inky" | "pinky" | "blinky" | "clyde";
    baz: {
        a: () => "inky" | "pinky" | "blinky" | "clyde";
        b: ["inky" | "pinky" | "blinky" | "clyde", "inky" | "pinky" | "blinky" | "clyde"];
        c: ("inky" | "pinky" | "blinky" | "clyde")[];
    };
    bing: Promise<"inky" | "pinky" | "blinky" | "clyde">;
    boom: Set<"inky" | "pinky" | "blinky" | "clyde">;
    bah: {
        a: Map<number, "inky" | "pinky" | "blinky" | "clyde">;
        b: Map<"inky" | "pinky" | "blinky" | "clyde", "inky" | "pinky" | "blinky" | "clyde">;
        c: Map<"inky" | "pinky" | "blinky" | "clyde", number>;
    }
}

实现方案

完全可行,通过TypeScript的条件类型、递归类型以及内置工具类型可以实现该需求,以下是完整的ReplaceTypes类型工具:

type ReplaceTypes<T, From, To> = 
    // 基础类型直接替换
    T extends From ? To :
    // 处理函数类型:替换参数和返回值
    T extends (...args: infer Args) => infer Return ?
        (...args: ReplaceTypes<Args, From, To>) => ReplaceTypes<Return, From, To> :
    // 处理元组类型:保留元组结构,替换每个元素
    T extends readonly [infer First, ...infer Rest] ?
        [ReplaceTypes<First, From, To>, ...ReplaceTypes<Rest, From, To>] :
    // 处理数组类型:替换元素类型
    T extends Array<infer U> ?
        Array<ReplaceTypes<U, From, To>> :
    // 处理Promise:替换泛型参数
    T extends Promise<infer U> ?
        Promise<ReplaceTypes<U, From, To>> :
    // 处理Set:替换泛型参数
    T extends Set<infer U> ?
        Set<ReplaceTypes<U, From, To>> :
    // 处理Map:替换键和值的类型
    T extends Map<infer K, infer V> ?
        Map<ReplaceTypes<K, From, To>, ReplaceTypes<V, From, To>> :
    // 处理对象类型:递归替换每个属性
    T extends object ?
        { [K in keyof T]: ReplaceTypes<T[K], From, To> } :
    // 其他类型直接返回
    T;

代码解释

  1. 基础类型替换:优先匹配要替换的目标类型,直接返回新类型
  2. 函数类型处理:通过infer提取参数列表和返回值,分别递归替换后重新构造函数类型
  3. 元组类型处理:用readonly [infer First, ...infer Rest]匹配元组结构,逐个替换元素后保留元组形态
  4. 数组类型处理:匹配数组并提取元素类型,替换后重新构造数组类型
  5. 泛型容器处理:分别处理Promise、Set、Map这类常见泛型容器,替换其内部的泛型参数
  6. 对象类型处理:遍历对象的所有键,递归替换每个属性的类型
  7. 兜底逻辑:未匹配到上述类型的,直接返回原类型

将该类型工具应用到测试用例中,即可得到预期的输出结果,完全满足递归替换嵌套类型且保留原有类型特性的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 05:33:17