如何定义公共成员非空、独有成员可空的TypeScript联合类型?
TypeScript 如何定义公共成员非可选、独有成员可选的联合兼容类型?
问题描述
我需要定义一个函数,它可以接收类型A或B作为参数,这两个类型有部分公共成员,也有各自独有的成员。我希望在函数体内能直接引用仅属于A或B的成员,同时明确这些成员在运行时可能为undefined,但公共成员必须保持非可选状态。
当前尝试的两种方式都无法满足需求:
- 使用
type ArgType = A | B:访问独有成员时TypeScript会报错,因为它无法确定当前参数是A还是B - 使用
type ArgType = A | B | Partial<A> | Partial<B>:会导致A和B的所有成员都变成可选,包括公共成员
示例代码如下:
type A = { common: number; a_only: string; } type B = { common: number; b_only: string; } type ArgType = A | B; // 无法满足需求:访问a_only/b_only会报错 function takesAorB(arg: ArgType) { if (arg.common > 1) { // 这里没问题,common在A和B中都存在且非可选 } if (arg.a_only?.length) { // 报错:属性'a_only'不存在于类型'B'上 } if (arg.b_only?.length) { // 报错:属性'b_only'不存在于类型'A'上 } }
解决方案
可以通过自定义工具类型,构造一个公共成员非可选、独有成员可选的类型,具体步骤如下:
- 提取两个类型的公共属性,保留其非可选状态
- 分别提取两个类型的独有属性,将其转为可选状态
- 将上述三部分交叉合并,得到最终的目标类型
实现代码:
type A = { common: number; a_only: string; } type B = { common: number; b_only: string; } // 提取两个类型的公共属性 type CommonProps<T, U> = Pick<T, Extract<keyof T, keyof U>>; // 提取类型T相对于U的独有属性 type UniqueProps<T, U> = Pick<T, Exclude<keyof T, keyof U>>; // 构造目标类型:公共属性非可选,两个类型的独有属性转为可选 type ArgType = CommonProps<A, B> & Partial<UniqueProps<A, B>> & Partial<UniqueProps<B, A>>; function takesAorB(arg: ArgType) { if (arg.common > 1) { // common仍为非可选,无需额外检查 } if (arg.a_only?.length) { // a_only的类型为string | undefined,符合预期 console.log(arg.a_only); } if (arg.b_only?.length) { // b_only的类型为string | undefined,符合预期 console.log(arg.b_only); } } // 测试用例:符合要求的参数都能正常传入 takesAorB({ common: 2, a_only: "test" }); takesAorB({ common: 3, b_only: "demo" }); takesAorB({ common: 1 }); // 也允许只传公共成员
原理说明
CommonProps<A, B>:提取A和B的共同键(这里是common),得到类型{ common: number },保留原有的非可选约束Partial<UniqueProps<A, B>>:提取A独有的键(a_only)并转为可选,得到{ a_only?: string }Partial<UniqueProps<B, A>>:提取B独有的键(b_only)并转为可选,得到{ b_only?: string }- 交叉类型
&会把这三部分合并,最终得到的类型既保证了公共成员的非可选性,又让独有成员变成可选(即类型为对应值或undefined)
内容的提问来源于stack exchange,提问作者JSBձոգչ
相关产品推荐
相关产品推荐

