2016-10-21 69 views
3

我有一個服務,我想用它從JSON返回指定類型構建的對象。Typescript調用通用類型的靜態方法

我有一個類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之前添加靜態文字,它告訴我:

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

回答

1

有幾件事情:

(1)接口不能有靜態的聲明,例如:

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

code in playground

在打字稿中解決這個問題的方法是定義一個構建器/構造器接口:

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; 
}()); 

code in 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