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

TypeScript中如何简洁定义仅含单个属性的互斥类型?

如何在TypeScript中定义「仅允许单个属性存在」的类型?

需求背景

需要定义一个包含多个可选属性的类型,但要求对象实例只能包含其中一个属性。比如原接口是这样的:

export interface OperatorExpression {
    equals?: any;
    lessThan?: any;
    lessThanOrEqualTo?: any;
    greaterThan?: any;
    greaterThanOrEqualTo?: any;
    contains?: any;
    // etc.
}

期望的约束效果:

const op1 = { equals: {}, greaterThanOrEqualTo: {} }; // 无效:同时存在多个属性
const op2 = { lessThanOrEqualTo: {} }; // 有效:仅单个属性

现有的实现是为每个属性单独定义接口,把其他属性设为never再联合,虽然能满足需求,但新增属性时要修改所有接口,样板代码繁琐且维护成本高。

简洁实现方案

方法1:映射类型+联合类型拆分写法

先定义所有操作符的键集合,再通过映射生成每个仅含单个属性的类型,最后联合起来:

// 第一步:定义所有操作符键的集合
type OperatorKeys = 'equals' | 'lessThan' | 'lessThanOrEqualTo' | 'greaterThan' | 'greaterThanOrEqualTo' | 'contains';

// 第二步:生成仅含单个指定属性的类型
type SingleOperator<K extends OperatorKeys> = {
  [P in K]: any; // 目标属性设为必填
} & {
  [P in Exclude<OperatorKeys, K>]?: never; // 其余属性只能是never或不存在
};

// 第三步:联合所有单属性类型
type OperatorExpression = SingleOperator<OperatorKeys>;

方法2:紧凑合并写法

可以把上面的逻辑合并成一行,无需单独定义SingleOperator:

type OperatorKeys = 'equals' | 'lessThan' | 'lessThanOrEqualTo' | 'greaterThan' | 'greaterThanOrEqualTo' | 'contains';

type OperatorExpression = {
  [K in OperatorKeys]: { [P in K]: any } & Partial<Record<Exclude<OperatorKeys, K>, never>>;
}[OperatorKeys];

效果验证

两种写法都能实现预期约束:

const op1 = { equals: {}, greaterThanOrEqualTo: {} }; // ❌ 类型错误:'greaterThanOrEqualTo'的类型不能赋值给never
const op2 = { lessThanOrEqualTo: {} }; // ✅ 类型正确
const op3 = { contains: 'test' }; // ✅ 类型正确
const op4 = { equals: 123, lessThan: 456 }; // ❌ 类型错误

维护优势

新增操作符时,只需要在OperatorKeys里添加新的键名即可,比如新增notEquals:

type OperatorKeys = 'equals' | 'lessThan' | 'lessThanOrEqualTo' | 'greaterThan' | 'greaterThanOrEqualTo' | 'contains' | 'notEquals';

不需要修改其他代码,自动生成对应的约束类型,彻底解决原方案的繁琐问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:15:32