TypeScript泛型实现:如何让方法接收继承A的类(非实例)数组
如何用泛型让方法接收继承自A的类数组(而非实例数组)?
嘿,刚好碰到过类似的问题!咱们先理清楚问题出在哪儿:你现在写的looper方法参数A[]指的是A类的实例数组,但你实际想要接收的是A或者其子类本身的数组(也就是构造函数的集合)。
先回顾一下你给出的类层级:
export class A { static m() { return 'a'; } } export class B extends A { static m() { return 'b'; } } export class C extends A { static m() { return 'c'; } }
原来的方法function looper(classes: A[]) { classes.forEach(c => c.m()); }里,c是A的实例,而实例是没有静态方法m()的——静态方法是挂在类本身的,不是实例上的,所以这就会导致类型错误(甚至运行时也会出错)。
解决办法:用泛型约束构造函数类型
在TypeScript中,类本身的类型是typeof 类名,比如typeof A就代表A类的构造函数类型。我们需要用泛型来约束数组元素是继承自A的类的构造函数,而不是实例。
修改后的方法如下:
function looper<T extends typeof A>(classes: T[]) { classes.forEach(c => { // 这里的c是类本身,所以可以直接调用静态方法m() console.log(c.m()); }); }
验证一下调用效果
现在你可以直接传入类本身的数组,完全符合类型要求:
// 正确调用,不会有类型错误 looper([B, C]); // 输出: // 'b' // 'c'
为什么这样可行?
typeof A获取的是A类的构造函数类型,包含了它的所有静态成员(比如static m())。T extends typeof A确保泛型T是A或者A的子类的构造函数类型,这样数组里的每个元素都继承了A的静态方法,同时子类重写的m()也能被正确识别。
如果你想更严谨一点,也可以显式定义构造函数类型:
type AConstructor = typeof A; function looper(classes: AConstructor[]) { classes.forEach(c => c.m()); }
不过用泛型的方式更灵活,比如后续如果需要用到子类的其他静态成员,泛型T会保留具体子类的类型信息。
内容的提问来源于stack exchange,提问作者Cec
相关产品推荐
相关产品推荐

