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

如何在带泛型的TypeScript类中用属性做类型守卫并确定条件类型?

解决方案:通过类型守卫关联泛型与运行时类型

问题核心在于TypeScript无法自动将类的泛型参数UN与实例属性useNumber的运行时检查关联,从而缩小input的类型。以下两种方案无需手动类型断言(as)即可解决:

方案一:自定义类型守卫函数

通过类方法定义类型守卫,明确泛型参数与运行时值的对应关系:

type X<T> = T extends true ? number : string;

export class A<UN extends boolean, I = X<UN>> {
  useNumber: UN;

  constructor(useNumber: UN) {
    this.useNumber = useNumber;
  }

  a(input: string): string {
    return `${input}j`;
  }

  b(input: number): number {
    return input * 2;
  }

  // 自定义类型守卫:判断当前实例是否为数字类型分支
  isNumberInstance(this: A<UN, I>): this is A<true, number> {
    return this.useNumber === true;
  }

  c(input: I): string {
    if (this.isNumberInstance()) {
      // TypeScript自动推断:input为number,可安全调用b方法
      return this.b(input).toString();
    } else {
      // TypeScript自动推断:input为string,可安全调用a方法
      return this.a(input).toString();
    }
  }
}

// 测试
const numInstance = new A(true);
numInstance.c(123); // 正常执行

const strInstance = new A(false);
strInstance.c("hello"); // 正常执行

关键细节:

  • 调整泛型定义:将I extends X<UN>改为I = X<UN>,确保I严格对应条件类型X<UN>,消除类型歧义。
  • 类型守卫函数:isNumberInstance通过this is A<true, number>告诉TypeScript,当useNumber为true时,当前实例的泛型参数UN固定为true,I固定为number;反之则对应false和string。

方案二:直接检查input类型

利用input的类型与useNumber的逻辑一致性,通过typeof直接缩小类型:

type X<T> = T extends true ? number : string;

export class A<UN extends boolean, I = X<UN>> {
  useNumber: UN;

  constructor(useNumber: UN) {
    this.useNumber = useNumber;
  }

  a(input: string): string {
    return `${input}j`;
  }

  b(input: number): number {
    return input * 2;
  }

  c(input: I): string {
    if (typeof input === 'number') {
      return this.b(input).toString();
    } else {
      return this.a(input).toString();
    }
  }
}

这种方式更简洁,因为input的类型I本身就是X<UN>的条件类型,与useNumber的逻辑完全匹配,TypeScript可直接通过typeof检查识别类型。

内容的提问来源于stack exchange,提问作者özüm

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 19:03:24