如何在TypeScript中构造满足{} | A | B | (A&B)的接口部分和类型?
构造TypeScript的离散接口「部分和」类型
我需要构造一个TypeScript类型S,使其成为若干离散接口(比如示例中的A和B)的「部分和」,即类型为{} | A | B | (A & B)。
我尝试了以下代码,但结果不符合预期(问题可能出在{}并非真正的空接口):
type A = { readonly a1: 1 } type B = { readonly b1: 1 readonly b2: 2 } type Maybe<T> = T | {} type S = Maybe<A> & Maybe<B> // 预期代数类型: C = ({} & {}) | (A & {}) | (A & B) | ({} & B) const value1: S = {} // 应该通过类型检查(不包含A或B的属性) const value2: S = {a1: 1} // 应该通过类型检查(包含A的属性) const value3: S = {b1: 1, b2: 2} // 应该通过类型检查(包含B的属性) const value4: S = {a1: 1, b1: 1, b2: 2} // 应该通过类型检查(同时包含A和B的属性) const value5: S = {d: 1} // 理想情况下不应该通过类型检查(`d`是多余属性) const value6: S = {a1: 2} // 不应该通过类型检查(不符合A的类型要求)
我已经考虑过Partial,但Partial<A> & Partial<B>并不等价于{} | A | B | (A & B),无法满足需求。请问能否实现这一类型?
解决方案
要实现这个「部分和」类型,核心是精确约束只能存在目标接口的完整属性集、空对象,且不允许多余属性。可以通过以下方式实现:
// 工具类型:确保对象只能包含指定类型的键,多余键会触发错误 type Exact<T, U extends T> = U & Record<Exclude<keyof U, keyof T>, never>; type A = { readonly a1: 1 } type B = { readonly b1: 1 readonly b2: 2 } // 直接枚举所有合法情况:空对象 | 完整A | 完整B | 完整A+B type S = | {} | Exact<A, A> | Exact<B, B> | Exact<A & B, A & B>; // 测试验证 const value1: S = {}; // ✅ 通过 const value2: S = {a1: 1}; // ✅ 通过 const value3: S = {b1: 1, b2: 2}; // ✅ 通过 const value4: S = {a1: 1, b1: 1, b2: 2}; // ✅ 通过 const value5: S = {d: 1}; // ❌ 报错:类型 { d: 1; } 不能赋值给类型 S const value6: S = {a1: 2}; // ❌ 报错:类型 2 不能赋值给类型 1
原理说明
Exact<T, U extends T>:这个工具类型通过Record<Exclude<keyof U, keyof T>, never>约束,确保U的键只能来自T,多余的键会被标记为never,从而触发类型错误。结合Exact<A, A>可以强制必须完整符合A的结构,同理处理B和A&B。- 直接枚举
{} | A | B | (A&B)并通过Exact约束,就能严格实现需求:只允许空对象、完整的A、完整的B,或同时完整的A+B,且不允许多余属性或不完整的接口属性。
如果需要支持更多接口的扩展,可以封装成通用工具类型:
type Exact<T, U extends T> = U & Record<Exclude<keyof U, keyof T>, never>; // 通用部分和类型:接收接口列表,生成空对象、单个完整接口、任意组合完整接口的联合类型 type PartialSum<T extends object[]> = | {} | { [K in keyof T]: Exact<T[K], T[K]> }[number] | { [K in keyof T]: Exact<T[K], T[K]> }[number] & { [K in keyof T]: Exact<T[K], T[K]> }[number]; // 使用示例 type S = PartialSum<[A, B]>;
后续添加新接口时,只需修改PartialSum的参数数组即可。
内容的提问来源于stack exchange,提问作者Bertrand Caron
相关产品推荐
相关产品推荐

