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

TypeScript联合类型类型谓词TS2677错误解决求助

解决TypeScript联合类型类型谓词的TS2677错误

我有多个由服务器生成的TypeScript联合类型,示例代码功能正常,但在WebStorm等编辑器中,类型谓词处触发TS2677错误:TS2677: A type predicate's type must be assignable to its parameter's type.。使用TypeScript 5.2.2,希望不借助@ts-ignore消除该错误。

原代码示例:

type KeysOfUnion<T> = T extends T ? keyof T : never;
export type ExtractValueTypeFromUnion<T, K extends KeysOfUnion<T>> = K extends string ?
    (T extends { [key in `${K}`]: infer ResultType } ?
        ResultType :
        never) :
    never

function isUnionVariant<U extends Record<string, any>, K extends KeysOfUnion<U>>(
    union: U,
    key: K
): union is K extends string ? { [key in `${K}`]: ExtractValueTypeFromUnion<U, K> } : never {
    return key in union;
}

type A = {
    "a": {
        a1: string
    }
} | {
    "b": {
        b1: string
    }
}

const doSomething = (a: A) => {
    if (isUnionVariant(a, "a")) {
        a.a.a1
    } else {
        a.b.b1
    }
}

解决方案

问题根源在于原类型谓词构造的新对象类型,未被TypeScript识别为联合类型U的子类型。我们可以通过直接从联合类型中筛选目标成员来修正:

type KeysOfUnion<T> = T extends T ? keyof T : never;

// 提取联合类型中包含指定key的成员类型
type UnionMemberWithKey<U, K extends KeysOfUnion<U>> = U extends Record<K, infer _V> ? U : never;

function isUnionVariant<U extends Record<string, any>, K extends KeysOfUnion<U>>(
    union: U,
    key: K
): union is UnionMemberWithKey<U, K> {
    return key in union;
}

type A = {
    "a": {
        a1: string
    }
} | {
    "b": {
        b1: string
    }
}

const doSomething = (a: A) => {
    if (isUnionVariant(a, "a")) {
        a.a.a1 // 类型推断正常
    } else {
        a.b.b1 // 类型推断正常
    }
}

说明

通过UnionMemberWithKey类型工具,直接从联合类型U中筛选出包含指定key K的成员,确保类型谓词返回的类型明确是U的子类型,从而消除TS2677错误,同时保留原有的类型推断能力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:32:53