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

TypeScript如何仅允许对象中键的特定组合?

问题:在TypeScript中定义严格约束的不等式对象类型

我想在TypeScript中定义一个表示不等式的对象类型,合法示例如下:

{ "<": x => Math.sin(x) } // 合法,y < sin(x)
{ ">": x => Math.sin(x) } // 合法,y > sin(x)
{ ">=": -4, "<": 4 } // 合法,-4 <= y < 4

但需要禁止无意义的组合,比如同时包含"小于"和"小于等于":

{ "<": 5, "<=": 5 } // 应触发TypeScript错误

我尝试了联合类型方案,但TypeScript会合并所有类型,允许任意键组合:

type Fn = number | ((x: number) => number)

type Inequality =
  | Record<">", Fn>
  | Record"<", Fn>
  | Record"<=", Fn>
  | Record">=", Fn>
  | Record<">" | "<", Fn>
  | Record<">" | "<=", Fn>
  | Record">=" | "<", Fn>
  | Record">=" | "<=", Fn>

是否可以让TypeScript仅允许我声明的键组合?


解决方案

之前的Record联合类型失效的核心原因是:Record<K, T>允许对象包含额外键,TypeScript的结构类型系统会认为"包含更多键的对象兼容目标类型"。要实现严格约束,需要明确禁止冲突键存在。

可以通过**互斥类型结合never**来实现,以下是两种可行写法:

写法1:分组约束(简洁版)

先将互斥的操作符分组,再定义允许的组合:

type Fn = number | ((x: number) => number);

// 互斥操作符分组:小于组、大于组
type LessOp = "<" | "<=";
type GreaterOp = ">" | ">=";

// 单个操作符的合法类型
type SingleInequality = 
  | { [K in LessOp]: Fn } 
  | { [K in GreaterOp]: Fn };

// 跨组组合的合法类型(仅允许一个大于组操作符 + 一个小于组操作符)
type CombinedInequality = 
  | { [K1 in GreaterOp]: Fn } & { [K2 in LessOp]: Fn };

// 最终的不等式类型
type Inequality = SingleInequality | CombinedInequality;

写法2:精确约束(严谨版)

通过& { [K in 冲突键]?: never }明确禁止冲突键,确保对象仅包含允许的键:

type Fn = number | ((x: number) => number);

type Inequality =
  // 单个大于操作符,禁止所有小于组操作符
  | ({ ">": Fn } & { [K in "<" | "<="]?: never })
  | ({ ">=": Fn } & { [K in "<" | "<="]?: never })
  // 单个小于操作符,禁止所有大于组操作符
  | ({ "<": Fn } & { [K in ">" | ">="]?: never })
  | ({ "<=": Fn } & { [K in ">" | ">="]?: never })
  // 跨组组合:大于组 + 小于组,禁止其他冲突键
  | ({ ">": Fn; "<": Fn } & { [K in ">=" | "<="]?: never })
  | ({ ">": Fn; "<=": Fn } & { [K in ">=" | "<"]?: never })
  | ({ ">=": Fn; "<": Fn } & { [K in ">" | "<="]?: never })
  | ({ ">=": Fn; "<=": Fn } & { [K in ">" | "<"]?: never });

验证效果

// 合法示例(无TS错误)
const valid1: Inequality = { "<": x => Math.sin(x) };
const valid2: Inequality = { ">": x => Math.sin(x) };
const valid3: Inequality = { ">=": -4, "<": 4 };

// 非法示例(触发TS错误)
const invalid1: Inequality = { "<": 5, "<=": 5 }; // 同时包含小于/小于等于,冲突
const invalid2: Inequality = { ">": 3, ">=": 3 }; // 同时包含大于/大于等于,冲突

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 13:05:17