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

使用类型谓词实现参数类型收窄的问题

如何通过类型谓词实现联合类型的完整字段收窄?

我希望基于单个字段的类型实现类型收窄,但TypeScript在使用类型谓词时,并未像在if语句中直接使用原始操作符那样,收窄类型中其他参数的类型。请问我该如何让类型收窄正常工作?

export function isTrue(input: boolean | undefined | null): input is true {
  return input === true;
}

type Refine =
  | {
      b: true;
      c: 'bIsTrue';
    }
  | {
      b: undefined;
      c: 'bIsUndefined';
    }
  | {
      b: false;
      c: 'bIsFalse';
    };

export function example() {
  const example = (null as unknown) as Refine;

  if (example.b === true) {
    example.b;  // Type is: true
    example.c;  // Type is: 'bIsTrue'
  }

  if (isTrue(example.b)) {
    example.b;  // Type is: true
    example.c;  // Type is: 'bIsTrue' | 'bIsUndefined' | 'bIsFalse'
  }
}

解决方案

问题根源在于当前的类型谓词仅针对example.b这个独立字段,TypeScript无法将单个字段的类型收窄关联到整个Refine联合类型的成员上。要实现完整的类型收窄,需要将类型谓词改为针对整个Refine对象的判断:

修改后的代码

export function isTrueRefine(input: Refine): input is Extract<Refine, { b: true }> {
  return input.b === true;
}

type Refine =
  | {
      b: true;
      c: 'bIsTrue';
    }
  | {
      b: undefined;
      c: 'bIsUndefined';
    }
  | {
      b: false;
      c: 'bIsFalse';
    };

export function example() {
  const example = (null as unknown) as Refine;

  if (example.b === true) {
    example.b;  // Type is: true
    example.c;  // Type is: 'bIsTrue'
  }

  if (isTrueRefine(example)) {
    example.b;  // Type is: true
    example.c;  // Type is: 'bIsTrue'
  }
}

原理说明

  • 使用Extract<Refine, { b: true }>从联合类型中精准提取出b字段为true的子类型
  • 类型谓词直接断言输入的整个对象属于该子类型,让TypeScript能够正确关联b和c的类型依赖关系,从而实现完整的类型收窄

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 12:33:19