TypeScript调用泛型类型的静态方法

18
我有一个服务,希望使用它来返回从JSON构建的指定类型对象。
我有一个类MyClass,它实现了一个静态类,该静态类定义了一个FromJSON静态方法。
export interface InterfaceMyClass {
    static FromJSON(json: any): any;
}

export class MyClass implements InterfaceMyClass {

    constructor(){}

    FromJSON(json: any): MyClass {
        let instance = MyClass.create(MyClass.prototype);
        Object.assign(instance, json);
        // Some other code specific to MyClass
        return instance;
    }
}

我不知道如何调用我在参数中传递的泛型类的静态方法,我的服务看起来像这样:

export class MyService<T extends InterfaceMyClass> {
    getObject() {
        let json = getExternalJson(...);
        return T.FromJSON(json); // <-- How to call static method FromJSON from T class ?
    }
}

我希望以以下方式使用该服务:
let service = new MyService<MyClass>();
let myObject = service.getObject(); // <-- Should by an MyClass instance (created by MyClass.FromJSON)

问题: 我如何调用T.FromJSON方法?

附加问题: 实现静态方法的好方法是什么?我不认为我的MyClass中的FromJSON方法是静态的。如果我在FromJSON之前添加static关键字,它会告诉我这个:

[ts] Class 'MyClass' incorrectly implements interface 'InterfaceMyClass'.
       Property 'FromJSON' is missing in type 'MyClass'.
1个回答

20

一些事情:

(1) 接口不能有静态声明,例如:

interface MyInterface {
    static myMethod(); // Error: 'static' modifier cannot appear on a type member
}

(在playground中的代码)

在TypeScript中解决这个问题的方法是定义一个构造器接口:

interface MyInterface {}

interface MyInterfaceBuilder {
    new (): MyInterface;
    myMethod();
}

(2) 通用约束只在编译时可用,但是由于javascript不支持它们,编译器会在之后将其移除,例如:

class MyClass<T extends string> {
    private member: T;

    constructor() {
        this.member = new T(); // Error: Cannot find name 'T'
    }
}

编译为:

var MyClass = (function () {
    function MyClass() {
        this.member = new T(); // Error: Cannot find name 'T'
    }
    return MyClass;
}());

(在playground中的代码)

当查看js输出时,很明显编译器会抛出Cannot find name 'T'错误,因为T无处可寻。

为了解决这个问题,这里提供一个解决方案:

interface IMyClass {}

interface IMyClassBuilder<T extends IMyClass> {
    new (): T;
    FromJSON(json: any): any;
}

class MyClass implements IMyClass {
    static FromJSON(json: any) {
        return "";
    }
}

class MyService<T extends IMyClass> {
    private classToCreate: IMyClassBuilder<T>;

    constructor(classToCreate: IMyClassBuilder<T>) {
        this.classToCreate = classToCreate;
    }

    getObject(): T {
        let json = getExternalJson(...);
        return this.classToCreate.FromJSON(json);
    }
}

let service = new MyService(MyClass);
let myObject = service.getObject();

(code in playground)


1
我想知道是否有任何方法可以这样编写代码,以便您可以使用 new MyService<MyClass>() 而不是 new MyService(MyClass) - jmjohnson85

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接