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

如何实现仅含两种类型之一键的TypeScript泛型OnlyOne?

TypeScript 实现仅允许单一类型键的泛型 OnlyOne<T, U>

需求是构建泛型类型OnlyOne<T, U>,要求该类型的实例只能包含类型T的任意键组合,或者类型U的任意键组合,绝对不允许同时包含T和U的键。

示例定义:

type A = {
  name?: string;
  email?: string;
};

type B = {
  x2?: number;
  phone?: string;
};

type C = OnlyOne<A, B>;

期望效果:

// ✅ 允许:仅使用A的键
const res1: C = { 
  name:'1'
}

// ✅ 允许:使用A的多个键
const res2: C = {
  name:'1',
  email:'email'
}

// ❌ 不允许:同时使用A和B的键
const res3: C = {
  name:'1',
  x2: 1
}

正确实现方式

type OnlyOne<T, U> = 
  // 允许T的任意可选键,禁止U独有的键
  (Partial<T> & Record<Exclude<keyof U, keyof T>, never>) | 
  // 允许U的任意可选键,禁止T独有的键
  (Partial<U> & Record<Exclude<keyof T, keyof U>, never>);

实现说明

  • Partial<T>:让T的所有键变为可选,支持任意子集组合(包括空对象)
  • Record<Exclude<keyof U, keyof T>, never>:生成一个类型,其中所有U有但T没有的键被设为never,意味着这些键绝对不能出现在实例中
  • 用|联合两种情况,确保实例只能属于其中一种场景,自然避免了混合T和U键的情况

原代码失效原因

你之前尝试的代码逻辑存在偏差:

type OnlyOne<T, U> = (T & U) extends infer O
  ? O extends T ? (Exclude<U, keyof T> & T) :
    O extends U ? (Exclude<T, keyof U> & U) : never
  : never;

T & U是同时包含T和U所有键的交叉类型,后续的O extends T或O extends U判断无法覆盖「T的子集」或「U的子集」的场景,本质上没有限制住混合键的情况,因此达不到需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 01:57:16