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

如何定义TypeScript联合类型:让可选接口属性全有或全无?

问题分析与解决方案

问题根源

你之前的写法type C = A | (A & B)不生效的核心原因是:TypeScript的结构类型系统中,A & B是A的子类型(它包含了A的所有属性),因此A | (A & B)会被TypeScript自动简化为A。这就意味着,只要对象满足A的结构要求,不管它有没有B的部分属性,都会被判定为合法——因为TypeScript会将其归为A类型,而A并不约束B的属性。

正确实现方案

要实现「要么完全包含B的所有属性,要么完全不包含B的任何属性」的约束,我们可以通过禁止部分B属性存在的方式来定义类型:

interface A {
  a1: string;
  a2: string;
}

interface B {
  b1: string;
  b2: string;
}

// 核心写法:要么拥有B的全部属性,要么完全没有B的属性
type C = A & (B | { [K in keyof B]?: never });

验证效果

  • 合法场景1:仅包含A的所有属性
    const c1: C = { a1: "a1", a2: "a2" }; // ✅ 正常通过
    
  • 合法场景2:包含A和B的所有属性
    const c2: C = { a1: "a1", a2: "a2", b1: "b1", b2: "b2" }; // ✅ 正常通过
    
  • 非法场景:仅包含部分B的属性
    const c3: C = { a1: "a1", a2: "a2", b2: "b2" }; // ❌ 报错:属性'b1'缺失,且b2的类型与never冲突
    

原理说明

{ [K in keyof B]?: never } 是一个工具类型,它将B的所有属性定义为可选但类型为never:

  • 当对象中不存在任何B的属性时,这个类型会和A交叉,得到纯A类型;
  • 当对象中存在任意一个B的属性时,TypeScript会尝试匹配B分支,此时就必须提供B的所有属性——否则会因为never类型约束(无法给never类型赋值)和B的属性缺失而报错。

其他尝试的问题解释

  • type C = A & (B | {}):{}是所有类型的父类型,因此这个写法等价于A,和最初的问题一致;
  • type C = A & (B | undefined):undefined和A交叉后会要求A的属性也可能为undefined,同时强制必须匹配B或undefined,导致纯A类型不合法,不符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 09:40:26