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

为何函数参数类型变为never?TypeScript泛型函数类型问题

TypeScript中stringify参数被推断为never的问题解决

问题根源

TypeScript无法在泛型函数中建立value参数与stringify方法参数的类型关联。虽然泛型Type约束了id是Dictionary的键,但items[id]会被推断为DictionaryItem<number> | DictionaryItem<boolean> | DictionaryItem<string>的联合类型。此时调用stringify(value)时,TypeScript无法将value的具体类型(Dictionary[Type]["value"])与联合类型中对应stringify的参数类型匹配,只能取所有stringify参数类型的交集——number & boolean & string的结果就是never,因此出现类型错误。

可行解决方案

方案1:类型断言明确关联

直接通过类型断言告诉TypeScript当前items[id]的stringify参数类型与value一致:

const update: UpdateFunction = (id, value) => {
    items[id].value = value;

    const item = items[id] as DictionaryItem<typeof value>;
    const stringified = item.stringify(value);

    console.log(stringified);
};

方案2:重构泛型函数强化类型关联

调整泛型约束逻辑,让TypeScript能清晰跟踪id、value与stringify的类型绑定:

// 直接让泛型对应value的类型,同时约束id必须匹配该value类型的键
const update = <T>(
    id: Extract<keyof Dictionary, { [K in keyof Dictionary]: Dictionary[K]["value"] extends T ? K : never }[keyof Dictionary]>,
    value: T
) => {
    items[id].value = value;
    const stringified = items[id].stringify(value);
    console.log(stringified);
};

这种写法不需要单独定义UpdateFunction类型,直接通过泛型约束保证类型安全。

方案3:类型守卫缩小范围

通过条件判断逐个缩小id的类型,让TypeScript在每个分支中明确stringify的参数类型:

const update: UpdateFunction = (id, value) => {
    items[id].value = value;

    let stringified: string | null;
    switch (id) {
        case "age":
            stringified = items[id].stringify(value as number);
            break;
        case "isNice":
            stringified = items[id].stringify(value as boolean);
            break;
        case "nickname":
            stringified = items[id].stringify(value as string);
            break;
        default:
            stringified = null;
    }

    console.log(stringified);
};

该方案适合字典键数量较少的场景,类型安全但代码量会随键数量增加而增长。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 03:27:47