为何联合类型会破坏我的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]>>后,问题依旧存在。
原因分析
泛型推断的交集规则:当传入
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>[]。
- 对于
条件返回类型的局限性:你添加的条件类型只处理了
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
相关产品推荐
相关产品推荐

