Typescript:将泛型类传递给函数参数

时间:2018-04-09 19:44:51

标签: typescript typescript2.0

我需要将class reference作为function parameter传递,并在此类上调用static method。将来,我可能需要创建一个类的实例,并添加一个构造函数作为示例。

我的工作没有打字:

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'

我正在尝试输入类引用,可能使用泛型,但对如何解决此问题感到困惑。

我尝试按照getMessage<C>(classRef: {new(): C;}): any {}...的方式做一些事情,但这些都没有用。

有人可以解释我如何正确传递课程参考?

1 个答案:

答案 0 :(得分:4)

一般来说,您必须使用构造函数类型引用typescript中的类。但是,从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是类构造函数,getMessage必须是一个静态方法),{{1 }表示new (...args: any[]): InstanceType<T>必须是类构造函数。

我已经将构造函数的参数设置为此处的任何内容,但如果您知道构造函数将始终采用特定参数,则可以进一步缩小范围。对于您的示例,T可以正常工作。

如果没有打字稿2.8,则无法使用new (id: number, message: string): InstanceType<T>。但是,您仍然可以通过让InstanceType表示实例类型,然后将参数类型设置为使用T作为参数的包装类型来获得类型安全性。所以对你的例子来说:

T

应该有用。