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

如何无需手动指定泛型实现TypeScript条件类型的正确收窄?

TypeScript 泛型联合类型的类型收窄问题

问题场景

你定义了如下类型:

type IInputType = "text" | "checkbox" | "number";

type IField<T extends IInputType> = {
  name: string;
  value: 
   T extends "checkbox" ? boolean : 
   T extends "number" ? number : 
   string;
  type: T;
};

// 无法实现正确类型收窄的定义
type IPossibleFieldTypes = IField<IInputType>;

此时存在问题:当变量类型为IPossibleFieldTypes时,即便通过field.type === "checkbox"做类型判断,field.value仍会被识别为string | number | boolean,而非预期的boolean。

但如果手动枚举泛型实例定义联合类型:

// 可正常收窄的手动枚举定义
type IPossibleFieldTypes =
  | IField<"text">
  | IField<"checkbox">
  | IField<"number">;

此时类型收窄正常,判断field.type === "checkbox"时,field.value会被正确识别为boolean。

解决方案:利用分布式条件类型自动生成联合类型

无需手动枚举泛型实例,我们可以借助TypeScript的分布式条件类型特性,让联合类型自动展开为对应成员的具体类型。

方法1:通过条件类型触发分发

type IInputType = "text" | "checkbox" | "number";

type IField<T extends IInputType> = {
  name: string;
  value: 
   T extends "checkbox" ? boolean : 
   T extends "number" ? number : 
   string;
  type: T;
};

// 自动生成可正确收窄的联合类型
type DistributeField<T extends IInputType> = T extends any ? IField<T> : never;
type IPossibleFieldTypes = DistributeField<IInputType>;

方法2:更简洁的写法

// 直接通过infer触发分布式条件类型
type IPossibleFieldTypes = IInputType extends infer U ? IField<U> : never;

原理说明

当条件类型的左侧是裸类型参数(即未被数组、对象等包裹的类型参数),且传入的是联合类型时,TypeScript会自动将联合类型的每个成员单独代入条件类型计算,最终将结果合并为新的联合类型。这样生成的IPossibleFieldTypes和手动枚举的版本完全等价,能够通过type属性实现精准的类型收窄。

验证示例

function handleField(field: IPossibleFieldTypes) {
  if (field.type === "checkbox") {
    field.value; // 类型为 boolean
  } else if (field.type === "number") {
    field.value; // 类型为 number
  } else {
    field.value; // 类型为 string
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 01:45:35