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

TypeScript如何限制泛型仅接受成员数大于1的联合类型?

实现泛型工具类型MoreThanOne<T, R>

要实现你需要的泛型工具类型,我们可以利用TypeScript的联合类型分发特性来判断一个类型是否为联合类型,进而返回对应的结果。以下是完整的解决方案:

步骤1:实现IsUnion类型判断工具

首先我们需要一个辅助类型来检测输入类型是否为联合类型:

type IsUnion<T, U = T> = 
  T extends U ? 
    [U] extends [T] ? false : true 
  : never;

原理说明:

  • 当T是联合类型时(比如Currency.EUR | Currency.USD),T extends U会触发TypeScript的分发特性,将联合类型拆分为单个成员分别判断。此时U是原始的联合类型,[U] extends [T]会判断原始联合类型是否能赋值给单个成员的数组类型——显然不能,因此返回true。
  • 当T是单个类型时(比如Currency.EUR),[U] extends [T]等价于[Currency.EUR] extends [Currency.EUR],返回true,因此外层条件返回false。

步骤2:实现MoreThanOne工具类型

基于IsUnion,我们可以写出目标工具类型:

type MoreThanOne<T extends R, R> = 
  IsUnion<T> extends true ? T : never;

逻辑说明:

  • 如果T是联合类型,直接返回T本身,允许函数接收该类型的参数;
  • 如果T不是联合类型(即单个成员),返回never,此时函数参数要求never类型,会触发编译错误。

完整示例验证

将你的代码和工具类型结合,验证效果:

enum Currency { EUR = "eur", USD = "usd", PLN = "pln", RUB = "rub" }
type Token<T extends Currency = Currency> = { type: T; value: string; };

const token1: Token<Currency.EUR> = { type: Currency.EUR, value: "1" }
const token2: Token<Currency.USD> = { type: Currency.USD, value: "1" }

const currencies = [token1, token2];
const currencyNonUnion = token1.type; // 类型:Currency.EUR
const currencyUnion = currencies[0].type; // 类型:Currency.EUR | Currency.USD

// 辅助类型
type IsUnion<T, U = T> = 
  T extends U ? 
    [U] extends [T] ? false : true 
  : never;

// 目标工具类型
type MoreThanOne<T extends R, R> = 
  IsUnion<T> extends true ? T : never;

// 测试函数
const foo = <T extends Currency>(curr: MoreThanOne<T, Currency>) => { /* 函数逻辑 */ }

foo(currencyUnion); // ✅ 编译通过,符合预期
foo(currencyNonUnion); // ❌ 编译错误:类型 "Currency.EUR" 不能赋值给类型 "never"

这样就完美实现了你需要的效果:仅允许传入联合类型的参数,单个类型参数会触发编译错误。

内容的提问来源于stack exchange,提问作者Paweł Lula

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 16:07:33