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

TypeScript如何定义含任意属性且a/b/c需同时存在的对象类型?

Solution to Enforce "All or None" for Specific Object Properties

Got it, let's tackle this TypeScript type problem you're facing. The core issue with a basic union type is that it doesn't block partial inclusion of a, b, or c—we need to explicitly define two mutually exclusive cases and combine them properly:

  1. The object has none of a, b, or c (but can have any other properties)
  2. The object has all three of a, b, and c (plus any other properties)

Step-by-Step Implementation

First, let's define the two distinct types, then combine them into a union:

// Type 1: Object has NO a/b/c properties (can have any other props)
type NoABC = Record<string, unknown> & {
  a?: never;
  b?: never;
  c?: never;
};

// Type 2: Object has ALL a/b/c properties (plus any other props)
// Replace string with your actual desired type for a/b/c
type HasABC = Record<string, unknown> & {
  a: string;
  b: string;
  c: string;
};

// Final union type enforcing "all or none" for a/b/c
type MyType = NoABC | HasABC;

How This Works

  • The NoABC type uses never for a, b, c to ensure those properties cannot exist (if you try to add any of them, TypeScript will throw an error because never can't be assigned to any value).
  • The HasABC type explicitly requires all three properties, while allowing extra properties via Record<string, unknown>.
  • The union ensures an object must fit one of these two cases—no partial inclusion allowed.

Test Cases to Validate

Let's check if this behaves as expected:

// ✅ Valid: No a/b/c, with other props
const valid1: MyType = { x: 42, name: "Alice" };

// ✅ Valid: Has all a/b/c, plus other props
const valid2: MyType = { a: "foo", b: "bar", c: "baz", isActive: true };

// ❌ Invalid: Only has 'a' (violates both NoABC and HasABC)
const invalid1: MyType = { a: "foo" };

// ❌ Invalid: Has 'a' and 'b' but no 'c'
const invalid2: MyType = { a: "foo", b: "bar" };

Generic Version (For Reusability)

If you want to reuse this pattern for other sets of properties or different types, create a generic type:

type RequireAllOrNone<Props extends string, PropType> = 
  // Case 1: None of the specified props exist
  (Record<string, unknown> & { [K in Props]?: never }) 
  | 
  // Case 2: All specified props exist with the given type
  (Record<string, unknown> & { [K in Props]: PropType });

// Usage example for a/b/c as numbers
type MyNumberType = RequireAllOrNone<'a' | 'b' | 'c', number>;

This way you can easily adapt the logic to other property sets or data types without rewriting the whole structure.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:13:58