[英]Typescript: Pass generic class to function parameter
I need to pass a class reference
as a function parameter
and invoke a static method
on this class. 我需要将
class reference
作为function parameter
传递,并在此类上调用static method
。 In the future, I might need to create an instance of the class and added a constructor as example. 将来,我可能需要创建类的实例并添加构造函数作为示例。
I have it working without typings: 我没有打字工作:
class Messages {
getMessage(classRef: any): any {
return classRef.getMessage()
}
}
class myClassA {
constructor(public id: number, public message: string) {}
static getMessage(): string {
return 'hello from class A';
}
}
class myClassB {
constructor(public id: number, public message: string) {}
static getMessage(): string {
return 'hello from class B';
}
}
var messages = new Messages();
var messageA = messages.getMessage(myClassA);
var messageB = messages.getMessage(myClassB);
console.log(messageA) // 'hello from class A'
console.log(messageB) // 'hello from class B'
I am trying to type the class reference, possibly with generics but confused about how to go about this. 我试图键入类引用,可能与泛型,但混淆如何去做。
I tried doing something along the lines of getMessage<C>(classRef: {new(): C;}): any {}...
but none of that is working. 我尝试按照
getMessage<C>(classRef: {new(): C;}): any {}...
做一些事情getMessage<C>(classRef: {new(): C;}): any {}...
但这些都没有用。
Can someone please explain how I can pass a class reference properly? 有人可以解释我如何正确传递课程参考?
Generally speaking, you have to refer to classes in typescript using their constructor type. 一般来说,您必须使用构造函数类型引用typescript中的类。 However, as of typescript 2.8, there is a new
InstanceType<T>
type in the standard lib that can extract the instance type from the constructor type. 但是,从typescript 2.8开始,标准库中有一个新的
InstanceType<T>
类型,可以从构造函数类型中提取实例类型。 You can use that here to get the type safety you want. 您可以在此处使用它来获得所需的类型安全性。
For your snippet, you might add types like so: 对于您的代码段,您可以添加如下类型:
class Messages {
getMessage<T extends {getMessage: () => string, new (...args: any[]): InstanceType<T>}>(classRef: T): string {
// Here, classRef is properly inferred to have a `getMessage` method.
return classRef.getMessage()
}
}
class myClassA {
constructor(public id: number, public message: string) {}
static getMessage(): string {
return 'hello from class A';
}
}
class myClassB {
constructor(public id: number, public message: string) {}
static getMessage(): string {
return 'hello from class B';
}
}
var messages = new Messages();
// messageA and messageB inferred to have type: string
// You can change that back to any if you want.
// myClassA and myClassB both assignable as the argument to
// getMessage, so no problem there.
var messageA = messages.getMessage(myClassA);
var messageB = messages.getMessage(myClassB);
console.log(messageA) // 'hello from class A'
console.log(messageB) // 'hello from class B'
The line 这条线
getMessage<T extends {getMessage: () => string, new (...args: any[]): InstanceType<T>}>(classRef: T): string {
is where the type safety comes from. 是类型安全的来源。 That syntax says that whatever
T
is, it has to have a method getMessage
(so if T is a class constructor, getMessage
has to be a static method), and the new (...args: any[]): InstanceType<T>
means that T
has to be a class constructor. 该语法说无论
T
是什么,它都必须有一个方法getMessage
(所以如果T是一个类构造函数, getMessage
必须是一个静态方法),那么new (...args: any[]): InstanceType<T>
表示T
必须是类构造函数。
I've set the arguments for the constructor to be anything here, but if you know that the constructor will always take specific arguments, you could further narrow that. 我已经将构造函数的参数设置为此处的任何内容,但是如果您知道构造函数将始终采用特定参数,则可以进一步缩小它。 For your example,
new (id: number, message: string): InstanceType<T>
would work. 对于您的示例,
new (id: number, message: string): InstanceType<T>
将起作用。
Without typescript 2.8, you can't use InstanceType
. 如果没有typescript 2.8,则无法使用
InstanceType
。 But you can still get type safety here by letting T
represent the instance type, and then setting the type of the parameter to be a wrapped type that uses T
as it's parameter. 但是,通过让
T
表示实例类型,然后将参数的类型设置为使用T
作为其参数的包装类型,您仍然可以获得类型安全性。 So for your example: 所以对于你的例子:
interface Messageable<T> {
new(...args: any[]): T;
getMessage(): string;
}
class Messages {
getMessage<T>(classRef: Messageable<T>): string {
return classRef.getMessage()
}
}
should work. 应该管用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.