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

TypeScript中如何在函数参数使用typeof并实现正确协变?

TypeScript按类过滤实例列表的问题解决

问题1:替代typeof T的写法

TypeScript不支持在泛型参数中直接使用typeof T指代类的构造函数类型。正确的做法是显式定义构造函数类型:new (...args: any[]) => T,它表示任何能生成T实例的构造函数,兼容任意参数列表。

问题2:实现协变支持

TypeScript没有out关键字,但若泛型参数T仅作为返回值类型(或只读位置)出现,编译器会自动启用协变。我们需要确保构造函数类型的定义不限制协变:使用new (...args: any[]) => T既适配带参数的构造函数,又让T保持协变能力。

完整可运行代码

class A {
}

class B extends A {
  constructor(pb: any) {
    super();
  }
}

class C extends A {
  constructor(pc: any) {
    super();
  }
}

function filterByClass<T extends A>(cls: new (...args: any[]) => T, list: A[]): T[] {
  // 添加类型守卫,让编译器识别过滤后的数组类型
  return list.filter((item): item is T => item instanceof cls);
}

// 使用示例
const a = new A();
const b = new B(1);
const c = new C(1);
const arr = [a, b, c];

const arrB = filterByClass(B, arr); // 类型推断为B[]
const arrC = filterByClass(C, arr); // 类型推断为C[]

关键细节

  • 类型守卫:item is T断言让filter的返回类型从A[]精确为T[],避免类型丢失。
  • 构造函数兼容性:(...args: any[])接受任意参数,解决了带参数构造函数的类型不匹配问题。
  • 协变验证:可以传入A的子类构造函数,返回对应子类数组;传入A构造函数则返回A[],完全符合协变预期。

内容的提问来源于stack exchange,提问作者Tom HANAX

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 17:50:41