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

如何让TypeScript对递归判别式联合类型进行类型推断?

TypeScript递归判别式联合类型的类型推断问题解析

为什么当前代码无法推断类型?

你当前的getItem函数返回类型被隐式推断为AnyItem(即Circle | Square | Bag),TypeScript无法跟踪传入的构造参数的递归嵌套结构:

  • 普通的类型守卫只能处理当前层级的类型判断,没法把输入参数的嵌套类型信息传递到返回值的嵌套结构中;
  • 函数返回的是顶层联合类型,TypeScript不知道某个具体的Bag构造参数对应的children里的每个元素会生成什么类型的Item,只能默认是AnyItem联合类型。

正确实现方案:泛型+条件类型映射

通过定义泛型类型来关联构造参数和最终Item的类型,让TypeScript能递归推断嵌套结构的类型:

步骤1:定义构造参数到Item的映射类型

首先创建一个泛型类型,根据构造参数的type字段,精确映射到对应的Item类型,包括嵌套的children:

type ConstructedItem<T extends AnyConstructorParams> = 
  T extends CircleConstructorParams ? Circle :
  T extends SquareConstructorParams ? Square :
  T extends BagConstructorParams ? Bag & { children: ConstructedItem<T['children'][number]>[] } :
  never;

这个类型会递归处理Bag的children,把每个子构造参数映射为对应的Item类型。

步骤2:修改getItem为泛型函数

让函数接收泛型参数,返回对应的ConstructedItem<T>类型:

function getItem<T extends AnyConstructorParams>(itemConstructorParams: T): ConstructedItem<T> {
    if (itemConstructorParams.type === 'circle') {
        return {
            type: 'circle',
            radius: 3,
        } as ConstructedItem<T>;
    } else if (itemConstructorParams.type === 'square') {
        return {
            type: 'square',
            sides: 4,
        } as ConstructedItem<T>;
    } else if (itemConstructorParams.type === 'bag') {
        return {
            type: 'bag',
            color: 'green',
            children: itemConstructorParams.children.map(child => getItem(child))
        } as ConstructedItem<T>;
    }
    throw new Error('Invalid');
}

这里的as ConstructedItem<T>是帮助TypeScript确认每个分支的返回值符合泛型映射的类型,属于辅助推导的断言,而非强制类型转换。

验证效果

现在执行测试代码,TypeScript可以精确推断每个嵌套Item的类型:

const circle = getItem({ type: 'circle' });
console.log(circle.radius); // 正确,类型为Circle

const square = getItem({ type: 'square' });
console.log(square.sides); // 正确,类型为Square

const nested = getItem({
    type: 'bag',
    children: [
        { type: 'square' },
        { type: 'circle' },
        {
            type: 'bag',
            children: [
                { type: 'square' },
                { type: 'circle' },
            ]
        },
    ],
});
console.log(nested.children[2].children[1].radius); // 正确,TypeScript能推断出这是Circle类型

关键原理

通过泛型把输入参数的类型和输出Item的类型绑定,再用条件类型递归处理嵌套结构,让TypeScript能沿着构造参数的嵌套层级,一步步推导出每个Item的精确类型,而不是退化为顶层的联合类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 22:37:41