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

如何在TypeScript中定义含可选值但至少一个必填的接口

在TypeScript中实现“至少一个属性必填”的接口

嘿,这个需求完全可以在TypeScript的类型系统层面解决,不用依赖运行时校验!咱们直接看方案:

核心思路:用联合类型替代单一接口

原来的ISearchKey把两个属性都设为可选,导致空对象也能通过类型检查。我们可以把它拆成两个子类型的联合——一个要求name必填(id可选),另一个要求id必填(name可选)。这样TypeScript会强制传入的对象至少匹配其中一个子类型,自然就避免了全空的情况。

实现代码

// 定义联合类型,保证至少有name或id中的一个
type ISearchKey = 
  | { name: string; id?: number }
  | { id: number; name?: string };

function findItem(search: ISearchKey): Item {
  // ... 你的业务逻辑
  return {} as Item;
}

// 测试合法情况
findItem({ name: "Alice" }); // ✅ 正常
findItem({ id: 123 }); // ✅ 正常
findItem({ name: "Bob", id: 456 }); // ✅ 正常(两个都填也允许)

// 测试非法情况
findItem({}); // ❌ TypeScript报错:类型“{}”不能赋值给类型“ISearchKey”

扩展:有更多公共属性的情况

如果你的搜索参数还有其他可选属性(比如age),可以把公共部分抽出来,用交叉类型合并,让代码更易维护:

// 公共可选属性
type CommonSearchProps = { age?: number; category?: string };

// 联合类型结合公共属性
type ISearchKey = 
  | ({ name: string } & CommonSearchProps)
  | ({ id: number } & CommonSearchProps);

// 测试:可以同时填name和age
findItem({ name: "Charlie", age: 30 }); // ✅ 正常

原理说明

联合类型的每个分支都明确了至少一个必填字段,TypeScript的类型检查器会验证传入的对象是否能匹配至少一个分支。空对象{}无法匹配任何一个分支(因为每个分支都要求至少有一个必填属性),所以会直接抛出类型错误,从根源上杜绝了不符合要求的输入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:18:58