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

如何在TypeScript中正确编写递归克隆函数的类型签名?

解决TypeScript递归类型克隆函数的类型不匹配问题

问题分析

你写的clone函数报错,核心原因是泛型T是Cloneable的子类型:当参数是数组时,arg.map(e => clone(e))返回的类型是Cloneable[],但T可能是更具体的数组类型(比如string[]),TypeScript无法确认Cloneable[]就是T,因此抛出类型不兼容的错误。

解决方案

通过递归条件类型精确推导输入与输出的类型关系,同时用类型断言辅助TypeScript完成类型匹配,无需使用any:

写法一:拆分基础类型与递归类型

// 定义基础可克隆类型
type BaseCloneable = string | number;
// 递归定义可克隆类型(基础类型或其数组)
type Cloneable = BaseCloneable | Cloneable[];

function clone<T extends Cloneable>(arg: T): T extends BaseCloneable ? T : Clone<T>[] {
    if (Array.isArray(arg)) {
        return arg.map(clone) as T;
    } else {
        return arg;
    }
}

// 辅助递归类型,处理数组元素的克隆类型
type Clone<T> = T extends BaseCloneable ? T : Clone<T>[];

写法二:直接用条件类型推断数组元素

type Cloneable = string | number | Cloneable[];

function clone<T extends Cloneable>(arg: T): T extends (infer U)[] ? Clone<U>[] : T {
    if (Array.isArray(arg)) {
        return arg.map(clone) as T;
    } else {
        return arg;
    }
}

// 递归推导克隆后的类型
type Clone<U> = U extends Cloneable ? (U extends (infer V)[] ? Clone<V>[] : U) : never;

原理说明

  • 用条件类型判断输入类型T:如果是数组,就递归推导其元素的克隆类型,返回对应的数组类型;如果是基础类型,直接返回原类型。
  • 类型断言as T是安全的,因为我们的条件类型已经保证了arg.map(clone)的返回类型和T完全匹配,TypeScript只是无法自动推导这层关系,需要我们明确告知。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:57:42