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

如何使用TypeScript的is关键字收窄泛型类型?

解决TypeScript泛型类类型替换而非交集的问题

你的问题出在TypeScript对普通类型守卫的处理逻辑上:当你用this is Foo<B>作为返回类型时,TypeScript会将原有泛型类型T与目标类型B取交集,因为它认为这是对原有类型的细化而非替换。要实现直接替换类型的效果,你需要使用**断言函数(asserts)**来替代普通类型守卫。

解决方案:使用asserts类型断言

将类中的is方法返回类型改为asserts this is Foo<B>,这样TypeScript会直接将this的类型替换为Foo<B>,而不是生成交集类型。

示例代码:

class Foo<T> {
  value!: T;
  // 使用asserts替代this is ...
  is = <B>(): asserts this is Foo<B> => {
    // 这里需要添加实际的运行时检查逻辑,确保value符合B类型
    // 示例中简化为直接通过,实际场景要根据需求判断
    return;
  };
}

const foo = new Foo<{ a: 'b', c: 'd' }>();

foo.value // { a: 'b', c: 'd' }

if (foo.is<{ c: 'd', e: 'f' }>()) {
  foo.value // 类型为 { c: 'd', e: 'f' },符合预期
}

针对Vehicle/Motorcycle场景的实际应用

结合你提到的车辆类型判断场景,我们可以写更严谨的代码,包含运行时检查:

type Vehicle = { wheels: number };
type Motorcycle = Vehicle & { type: 'motorcycle', hasSidecar: boolean };

class VehicleContainer<T extends Vehicle> {
  value!: T;

  constructor(value: T) {
    this.value = value;
  }

  // 专门的Motorcycle类型断言方法
  assertIsMotorcycle(): asserts this is VehicleContainer<Motorcycle> {
    // 运行时检查:确保value包含motorcycle的特征
    const vehicle = this.value as unknown;
    if (
      typeof vehicle !== 'object' || vehicle === null ||
      (vehicle as any).type !== 'motorcycle' ||
      typeof (vehicle as any).hasSidecar !== 'boolean'
    ) {
      throw new Error('当前车辆不是摩托车类型');
    }
  }
}

// 测试普通车辆
const car = new VehicleContainer<Vehicle>({ wheels: 4 });
car.value; // 类型为Vehicle

try {
  car.assertIsMotorcycle();
  car.value; // 这里不会执行,因为断言会抛出错误
} catch (err) {
  console.log(err.message); // 输出:当前车辆不是摩托车类型
}

// 测试摩托车
const motorcycle = new VehicleContainer<Motorcycle>({
  wheels: 2,
  type: 'motorcycle',
  hasSidecar: false
});
motorcycle.assertIsMotorcycle();
motorcycle.value; // 类型为Motorcycle,已成功替换

关键说明

  • asserts语句会直接修改变量的类型,而非细化原有类型,因此不会产生交集。
  • 必须添加对应的运行时检查逻辑,否则会导致类型不安全(TypeScript会信任你的断言,但运行时可能不符合类型定义)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:27:53