打字稿:将泛型 class 传递给函数参数
Typescript: Pass generic class to function parameter
我需要将 class reference
作为 function parameter
传递并在此 class 上调用 static method
。将来,我可能需要创建 class 的实例并添加一个构造函数作为示例。
我不用打字就能工作:
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'
我正在尝试键入 class 参考,可能使用泛型但不知道如何去做。
我尝试按照 getMessage<C>(classRef: {new(): C;}): any {}...
的方式做一些事情,但是 none 是可行的。
有人可以解释一下如何正确传递 class 引用吗?
一般来说,你必须使用它们的构造函数类型在 typescript 中引用 classes。但是,从 TypeScript 2.8 开始,标准库中有一个新的 InstanceType<T>
类型可以从构造函数类型中提取实例类型。您可以在此处使用它来获得所需的类型安全性。
对于您的代码段,您可以添加如下类型:
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'
行
getMessage<T extends {getMessage: () => string, new (...args: any[]): InstanceType<T>}>(classRef: T): string {
是类型安全的来源。该语法表示无论 T
是什么,它都必须有一个方法 getMessage
(因此如果 T 是一个 class 构造函数,则 getMessage
必须是一个静态方法),并且new (...args: any[]): InstanceType<T>
意味着 T
必须是 class 构造函数。
我在这里将构造函数的参数设置为任意值,但如果您知道构造函数将始终采用特定参数,则可以进一步缩小范围。对于您的示例,new (id: number, message: string): InstanceType<T>
会起作用。
没有 typescript 2.8,您将无法使用 InstanceType
。但是您仍然可以通过让 T
表示实例类型,然后将参数的类型设置为使用 T
作为参数的包装类型来获得类型安全。所以对于你的例子:
interface Messageable<T> {
new(...args: any[]): T;
getMessage(): string;
}
class Messages {
getMessage<T>(classRef: Messageable<T>): string {
return classRef.getMessage()
}
}
应该可以。
我需要将 class reference
作为 function parameter
传递并在此 class 上调用 static method
。将来,我可能需要创建 class 的实例并添加一个构造函数作为示例。
我不用打字就能工作:
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'
我正在尝试键入 class 参考,可能使用泛型但不知道如何去做。
我尝试按照 getMessage<C>(classRef: {new(): C;}): any {}...
的方式做一些事情,但是 none 是可行的。
有人可以解释一下如何正确传递 class 引用吗?
一般来说,你必须使用它们的构造函数类型在 typescript 中引用 classes。但是,从 TypeScript 2.8 开始,标准库中有一个新的 InstanceType<T>
类型可以从构造函数类型中提取实例类型。您可以在此处使用它来获得所需的类型安全性。
对于您的代码段,您可以添加如下类型:
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'
行
getMessage<T extends {getMessage: () => string, new (...args: any[]): InstanceType<T>}>(classRef: T): string {
是类型安全的来源。该语法表示无论 T
是什么,它都必须有一个方法 getMessage
(因此如果 T 是一个 class 构造函数,则 getMessage
必须是一个静态方法),并且new (...args: any[]): InstanceType<T>
意味着 T
必须是 class 构造函数。
我在这里将构造函数的参数设置为任意值,但如果您知道构造函数将始终采用特定参数,则可以进一步缩小范围。对于您的示例,new (id: number, message: string): InstanceType<T>
会起作用。
没有 typescript 2.8,您将无法使用 InstanceType
。但是您仍然可以通过让 T
表示实例类型,然后将参数的类型设置为使用 T
作为参数的包装类型来获得类型安全。所以对于你的例子:
interface Messageable<T> {
new(...args: any[]): T;
getMessage(): string;
}
class Messages {
getMessage<T>(classRef: Messageable<T>): string {
return classRef.getMessage()
}
}
应该可以。