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

为何联合类型会破坏我的TypeScript函数返回类型?

TypeScript中联合类型传入transform函数返回never类型的问题解析

问题代码与现象

export interface KeyValue<K, V> {
    key: K;
    value: V;
}

declare function transform<T, K extends keyof T>(input: T): Array<KeyValue<K, T[K]>>;

interface MyInterface {
    one?: string;
    two?: string;
    three?: string;
}

declare const myData: MyInterface | null;    
const foo = transform(myData) // 返回类型为 KeyValue<never, never>[]

尝试给transform添加条件返回类型T extends null ? null : Array<KeyValue<K, T[K]>>后,问题依旧存在。

原因分析

  1. 泛型推断的交集规则:当传入MyInterface | null这种联合类型时,TypeScript会对联合类型的每个分支单独推断泛型参数,再将各分支的推断结果取交集。

    • 对于null分支:keyof null的结果是never,因此K extends keyof null只能是never,对应的T[K]也为never。
    • 对于MyInterface分支:K被推断为"one" | "two" | "three",返回类型是Array<KeyValue<"one" | "two" | "three", string | undefined>>。
    • 两个分支的返回类型取交集后,never与"one" | "two" | "three"的交集仍是never,最终就得到了KeyValue<never, never>[]。
  2. 条件返回类型的局限性:你添加的条件类型只处理了T的分支,但K是独立于T的泛型参数。当T为联合类型时,K的推断依然会对每个分支执行后取交集,因此无法改变K被推断为never的结果。

解决方法

方法1:调整泛型结构,使用分布式条件类型

将K的推断合并到T的处理中,利用TypeScript的分布式条件类型对联合类型分支分别处理:

export interface KeyValue<K, V> {
    key: K;
    value: V;
}

declare function transform<T>(input: T): T extends null 
  ? null 
  : Array<KeyValue<keyof T, T[keyof T]>>;

interface MyInterface {
    one?: string;
    two?: string;
    three?: string;
}

declare const myData: MyInterface | null;    
const foo = transform(myData); // 类型为 Array<KeyValue<"one" | "two" | "three", string | undefined>> | null

方法2:提前排除null分支

通过非空断言或类型守卫先将null从联合类型中移除,再传入函数:

// 非空断言
const foo = transform(myData!); // 类型为 Array<KeyValue<"one" | "two" | "three", string | undefined>>

// 类型守卫
if (myData) {
    const foo = transform(myData); // 类型为 Array<KeyValue<"one" | "two" | "three", string | undefined>>
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 01:13:27