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

如何定义至少包含一个true值的布尔对象类型

如何定义至少包含一个true值的布尔对象类型

嘿,我完全懂你想实现的需求——要确保AgeDivisions和EventStyles这两个类型的实例,至少有一个属性的值是true对吧?其实用泛型来做是最优雅的方案,既能避免重复代码,又能让所有类似的布尔对象类型都复用同一个约束逻辑。

核心思路:泛型约束类型

我们可以创建一个通用的泛型类型AtLeastOneTrue<T>,它接受一个布尔属性的对象类型T,然后约束这个对象必须至少有一个属性为true。具体实现如下:

// 定义泛型类型:确保传入的布尔对象至少有一个true值
type AtLeastOneTrue<T extends Record<string, boolean>> = {
  // 保留原类型的所有属性结构
  [K in keyof T]: T[K]
} & {
  // 生成一个联合类型:每个成员对应某一个属性为true,其余属性可选为false
  [K in keyof T]: { [P in K]: true } & { [P in Exclude<keyof T, K>]?: false }
}[keyof T];

这个类型的逻辑是:

  1. 第一部分{ [K in keyof T]: T[K] }保留原类型的完整结构;
  2. 第二部分生成一个联合类型,每个联合成员对应原类型中某一个属性强制为true,其他属性则是可选的false;
  3. 通过交叉类型&把两部分结合,最终就确保了对象至少有一个属性是true。

应用到你的类型上

接下来把这个泛型应用到你现有的AgeDivisions和EventStyles上,再更新EventInfo类型即可:

type AgeDivisions = {
  youth: boolean;
  middleSchool: boolean;
  highSchool: boolean;
  college: boolean;
  open: boolean;
};

type EventStyles = {
  folkstyle: boolean;
  freestyle: boolean;
  grecoRoman: boolean;
  jello: boolean;
  noGiJits: boolean;
  giJits: boolean;
  judo: boolean;
  beach: boolean;
};

// 生成符合约束的有效类型
type ValidAgeDivisions = AtLeastOneTrue<AgeDivisions>;
type ValidEventStyles = AtLeastOneTrue<EventStyles>;

// 假设你已经定义了EventType类型
type EventType = "tournament" | "workshop" | "exhibition";

type EventInfo = {
  name: string;
  venueName: string;
  address: string;
  date: string;
  subTitle: string;
  country: string;
  eventType: EventType;
  hasGirlsOnlyDivision: boolean;
  link: string;
  ageDivisions: ValidAgeDivisions; // 替换成约束后的类型
  eventStyles: ValidEventStyles;   // 替换成约束后的类型
  latitude: string;
  longitude: string;
  description: string;
};

验证效果

现在如果尝试创建一个所有属性都是false的ValidAgeDivisions对象,TypeScript会直接报错:

// ❌ 错误:所有属性都是false,不符合约束
const invalidAgeDivisions: ValidAgeDivisions = {
  youth: false,
  middleSchool: false,
  highSchool: false,
  college: false,
  open: false
};

// ✅ 正确:至少有一个属性是true
const validAgeDivisions: ValidAgeDivisions = {
  youth: true,
  middleSchool: false,
  highSchool: false,
  college: false,
  open: false
};

备选方案:单独定义约束(不推荐)

如果你觉得泛型有点绕,也可以为每个类型单独写约束,但这种方式会产生大量重复代码,维护成本很高,比如:

type ValidAgeDivisions = 
  | { youth: true } & Partial<Record<Exclude<keyof AgeDivisions, 'youth'>, false>>
  | { middleSchool: true } & Partial<Record<Exclude<keyof AgeDivisions, 'middleSchool'>, false>>
  | { highSchool: true } & Partial<Record<Exclude<keyof AgeDivisions, 'highSchool'>, false>>
  | { college: true } & Partial<Record<Exclude<keyof AgeDivisions, 'college'>, false>>
  | { open: true } & Partial<Record<Exclude<keyof AgeDivisions, 'open'>, false>>;

显然这种方式不如泛型简洁,所以还是更推荐用泛型方案。

备注:内容来源于stack exchange,提问作者Wayne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 14:25:28