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

类型谓词能否与泛型条件类型配合使用?

TypeScript类型守卫无法正确收窄条件类型参数的问题

我写了一段TypeScript代码,期望通过类型谓词的类型守卫把props的类型收窄为StrLike<T>,但实际得到的类型却是(T extends string ? ObjLike<T> : StrLike<T>) & StrLike<T>,达不到预期的收窄效果:

type ObjLike<T> = {
    kind: "object";
    options: T[];
};

type StrLike<T> = {
    kind: "string";
    options: T[];
};

function fn<T>(props: T extends string ? ObjLike<T> : StrLike<T>) {
    function isStrGuard(item: ObjLike<T> | StrLike<T>): item is StrLike<T> {
        return item.kind === "string";
    }
    if (isStrGuard(props)) {
        /**
         * expected type: props: StrLike<T>
         * actual type: props: (T extends string ? ObjLike<T> : StrLike<T>) & StrLike<T>
         */
        props;
    }
}

问题原因

props的类型是条件类型,它的结果依赖于泛型T的具体类型。在泛型T未被具体化(还没传入具体类型参数)时,TypeScript没办法确定条件类型会走到哪个分支,所以在类型守卫后只能保留条件类型和StrLike<T>的交叉类型,无法直接简化为单纯的StrLike<T>。

解决方案

方案1:使用函数重载明确分支类型

通过给函数添加重载签名,把不同泛型分支下的参数类型明确出来,TypeScript就能正确识别类型守卫后的类型:

type ObjLike<T> = {
    kind: "object";
    options: T[];
};

type StrLike<T> = {
    kind: "string";
    options: T[];
};

// 当T是string类型时,参数为ObjLike<T>
function fn<T extends string>(props: ObjLike<T>): void;
// 当T不是string类型时,参数为StrLike<T>
function fn<T>(props: StrLike<T>): void;
// 函数实现
function fn<T>(props: ObjLike<T> | StrLike<T>) {
    function isStrGuard(item: ObjLike<T> | StrLike<T>): item is StrLike<T> {
        return item.kind === "string";
    }
    if (isStrGuard(props)) {
        props; // 现在类型正确收窄为StrLike<T>
    }
}

方案2:重构参数类型为联合类型

把条件类型拆成联合类型,结合never来排除不符合的分支,也能让类型守卫正常工作:

type ObjLike<T> = {
    kind: "object";
    options: T[];
};

type StrLike<T> = {
    kind: "string";
    options: T[];
};

function fn<T>(props: (T extends string ? ObjLike<T> : never) | StrLike<T>) {
    function isStrGuard(item: ObjLike<T> | StrLike<T>): item is StrLike<T> {
        return item.kind === "string";
    }
    if (isStrGuard(props)) {
        props; // 类型为StrLike<T>
    } else {
        props; // 类型为ObjLike<T>(仅当T是string时)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 04:40:58