如何在TypeScript中实现必选单个可选属性的类型约束?
更简洁实现“必选且仅选单个属性”的TypeScript类型定义
针对你需要实现「必须且只能定义接口中某一个属性」的需求,无需手动编写多个单个属性必选的接口,可通过映射类型+联合类型的方式动态生成目标类型,代码更简洁且易于维护(后续新增属性时无需修改类型定义)。
实现代码
// 基础可选属性接口 export interface OptionalIds { entityA_Id?: number; entityB_Id?: number; entityC_Id?: number; } // 工具类型:生成仅指定键必选、其余键为undefined的类型 type ExactlyOne<T, K extends keyof T = keyof T> = K extends keyof T ? { [P in keyof T]: P extends K ? T[P] : undefined } & { [P in K]-?: Exclude<T[P], undefined> } : never; // 最终目标类型:必选且仅能选OptionalIds中的一个属性 export type RestrictedOptionalIds = ExactlyOne<OptionalIds>;
代码解释
ExactlyOne<T, K>是泛型工具类型:- 遍历
T的所有键K,对每个键生成两种约束的交叉类型:- 所有键的类型:如果是当前遍历的
K则保留原类型,否则设为undefined(确保其余属性无法传入有效值) - 强制当前
K为必选属性(通过-?移除可选修饰符),并排除undefined(确保该属性必须传入有效值)
- 所有键的类型:如果是当前遍历的
- 遍历
- 最终
RestrictedOptionalIds会自动展开为「仅entityA_Id必选」「仅entityB_Id必选」「仅entityC_Id必选」三种类型的联合,完全满足需求。
验证示例
// 合法:仅传入entityA_Id const valid1: RestrictedOptionalIds = { entityA_Id: 1 }; // 合法:仅传入entityB_Id const valid2: RestrictedOptionalIds = { entityB_Id: 2 }; // 不合法:传入多个属性 const invalid1: RestrictedOptionalIds = { entityA_Id: 1, entityB_Id: 2 }; // 类型报错 // 不合法:未传入任何属性 const invalid2: RestrictedOptionalIds = {}; // 类型报错
内容的提问来源于stack exchange,提问作者RQman
相关产品推荐
相关产品推荐

