[英]Typescript generic class type with static methods
Suppose I have these classes假设我有这些课程
abstract class Animal {
public static getSound(): string {
throw new Error("Abstract animal has no sound");
}
}
class Dog extends Animal {
public static getSound(): string {
return "Woof";
}
}
class Cat extends Animal {
public static getSound(): string {
return "Meow";
}
}
// Other animal classes...
And I want to write a function that takes a generic subclass of Animal, ie not instance of subclass, as a parameter and calls the corresponding static method getSound
.我想编写一个 function ,它将 Animal 的通用子类(即不是子类的实例)作为参数并调用相应的 static 方法
getSound
。 This is what I've tried so far.这是我到目前为止所尝试的。
interface ClassType<T = any> {
new (...args: any[]): T;
}
const getAnimalSound = <T extends Animal>(type: () => ClassType<T>) => {
return type().getSound(); // Property 'getSound' does not exist on type 'ClassType '.
};
console.log(() => Dog); // should print "Woof"
console.log(() => Cat); // should print "Meow"
But I'm getting the compile error Property 'getSound' does not exist on type 'ClassType'
.但是我收到编译错误
Property 'getSound' does not exist on type 'ClassType'
。 The meaning of the error is obvious, I didn't set up the types correctly, .错误的意思很明显,我没有正确设置类型,. How should I go about doing this, without redesigning the classes ?
我应该如何 go 这样做,而不重新设计类?
Thanks all.谢谢大家。
ClassType
should be declared as ClassType
应声明为
type ClassType = typeof Dog | typeof Cat;
And the getAnimalSound
should be transformed into: getAnimalSound
应该转换为:
const getAnimalSound = (type: ClassType): string => type.getSound();
Now, if we call现在,如果我们打电话
console.log(getAnimalSound(Dog));
console.log(getAnimalSound(Cat));
their sounds can be heard.可以听到他们的声音。
The issue in the original approach is that the static
methods belong to the class object and they cannot be invoked on an instance, so we need to access the type reference.原始方法中的问题是
static
方法属于 class object 方法,它们不能在实例上调用,因此我们需要访问类型引用。
In fact, the static "inheritance" in the original approach does not make sense, because these methods are invoked as Animal.getSound()
, Dog.getSound()
etc.实际上,原方法中的 static “继承”没有意义,因为这些方法被调用为
Animal.getSound()
、 Dog.getSound()
等。
I think perhaps the type for getAnimalSound
is not accurate.我认为
getAnimalSound
的类型可能不准确。
The argument should be a function which returns Animal
constructors, not instances .参数应该是一个 function ,它返回
Animal
构造函数,而不是instance 。 Looks like you're aware of that, as you've written ClassType<T>
to be a type that represents a constructor for instances of type T
.看起来您已经意识到这一点,因为您已将
ClassType<T>
编写为表示T
类型实例的构造函数的类型。 That is almost right, but the critical thing is ClassType<T>
only has information on the constructor signature, it has lost all the information on the static members of the class.这几乎是对的,但关键是
ClassType<T>
只有构造函数签名的信息,它丢失了 class 的 static 成员的所有信息。 This is what leads to your error.这就是导致您的错误的原因。
One little known feature of typescript is that if a type T
represents the type of an instance of a class, then the type typeof T
(as weird as that looks) represents the constructor type , including all static members! typescript 的一个鲜为人知的特性是,如果类型
T
表示 class实例的类型,那么typeof T
(看起来很奇怪)表示构造函数类型,包括所有 ZA81259CEF8E959C2297DF1D456E35 成员!
So your type for getAnimalSound
could be simplified:因此,您的
getAnimalSound
类型可以简化:
const getAnimalSound<T extends typeof Animal>(type: () => T) => {
return type().getSound() // No Error!
}
Using that, seems like you will get the desired result::使用它,似乎你会得到想要的结果::
console.log(getAnimalSound(() => Dog)) // Logs: "Woof".
console.log(getAnimalSound(() => Cat)) // Logs: "Meow".
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.