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

TypeScript条件类型与可选属性兼容问题及实现等效类型的方法

TypeScript条件类型与可选属性的分发问题解决办法

在TypeScript中,条件类型与可选属性结合时,不会自动对条件分支进行分发。看下面的示例:

type A<X> = (X extends string ? { stringValue: X } : { otherValue: X });
type B<X> = A<X> & { optionalValue?: number }

function func<X>(arg: B<X>) {}

function test1<X>(arg: A<X>) { func(arg); }                           // 报错
function test2<X>(arg: A<X>) { func({ ...arg }); }                    // 报错
function test3<X>(arg: A<X>) { func({ ...arg, optionalValue: 42 }); } // 正常
function test4<X>(arg: A<X> & {}) { func({ ...arg }); }               // 正常

test1和test2的错误提示为:Argument of type 'A<X>' is not assignable to parameter of type 'A<X> & { optionalValue?: number | undefined; }'.

当显式提供可选属性optionalValue时,test3可以正常运行;通过& {}强制低优先级类型推断时,test4也能正常运行。

我们预期B<X>的等效类型是:

X extends string
  ? { stringValue: X } & { optionalValue?: number }
  : { otherValue: X } & { optionalValue?: number }

实现方法

要让条件类型的每个分支都能和可选属性交叉,我们需要让B<X>成为分布式条件类型——也就是让类型参数X以“裸类型”的形式出现在条件判断中,触发TypeScript的分布式分发逻辑。

有两种常见实现方式:

方式1:直接重写B的条件逻辑

直接将可选属性的交叉逻辑嵌入到每个条件分支中,和预期结构一致:

type A<X> = X extends string ? { stringValue: X } : { otherValue: X };
type B<X> = X extends string
  ? { stringValue: X } & { optionalValue?: number }
  : { otherValue: X } & { optionalValue?: number };

方式2:利用分布式条件类型复用A的逻辑

如果不想重复A<X>的分支逻辑,可以通过infer触发分布式分发:

type A<X> = X extends string ? { stringValue: X } : { otherValue: X };
type B<X> = X extends infer T ? A<T> & { optionalValue?: number } : never;

这两种方式都能让B<X>的类型按条件分支分别与可选属性交叉,此时test1和test2都可以正常编译,无需额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 02:05:23