2017-10-18 253 views
0

功能接口我想要一類的行爲像JS日期功能:打字稿:與構造

  1. 當通過new稱它創建類的實例。
  2. 當作爲一個函數被調用時,它會做一些靜態的東西。

我該如何實現這個接口?

interface A { 
    (): string; 
    new(arg: number); 
    GetValue(): number; 
} 

當前的解決方案無法編譯,但產生正確的JS代碼在操場:

class B implements A { 

    private Value: number; 

    constructor(arg: number) { 
     if (this.constructor == B) { 
      this.Value = arg; 
     } else { 
      return "42"; 
     } 
    } 

    GetValue(): number { 
     return this.Value; 
    } 
} 

回答

1

不能使用ES2015laterclass讓你調用構造函數沒有new關鍵字。在鏈接文檔的第9.2.1節的第2步中,調用沒有new關鍵字的類構造函數應導致引發TypeError。 (如果你在TypeScript中定位ES5,你會得到一些在運行時可以工作的東西,但是如果你的目標是ES2015或者更高版本,你將會得到運行時錯誤,所以最好不要這樣做。)所以要實現你的接口,你需要使用pre -ES2015構造函數代替。


順便說一下,new(arg: number)簽名需要返回類型。例如:

interface A { 
(): string; 
    new(arg: number): AInstance; // return something 
    GetValue(): number; 
} 
// define the instance type 
interface AInstance { 
    instanceMethod(): void; 
} 

下面是實現的一個方法。首先,做一個classAInstance

class _A implements AInstance { 
    constructor(arg: number) { } // implement 
    instanceMethod() { } // implement 
} 

然後,做一個可以帶或不帶new調用的函數:

const AFunctionLike = 
    function(arg?: number): AInstance | string { 
    if (typeof arg !== "undefined") { 
     return new _A(arg); 
    } 
    return "string"; 
    } as { new(arg: number): AInstance,(): string }; 

我已經決定,如果調用AFunctionLike與參數,那麼你將獲得AInstance,否則您將獲得string。如果您的運行時支持它,您還可以通過new.target明確檢查是否使用了new

另外請注意,我不得不斷言AFunctionLike是newable(與最後一行as條款),因爲目前尚未有其他的方式來告訴打字稿是一個獨立的函數可以用new被調用。我們差不多完成了。

const A: A = Object.assign(
    AFunctionLike, 
    { 
    GetValue() { 
     return 1; 
    } 
    } 
); 

A已經通過使用實現GetValue()對象合併AFunctionLike形成:我們可以如下聲明A類型的值。您可以使用Object.assignspread syntax進行合併。


就是這樣。你可以驗證這在運行時on the TypeScript Playground。祝你好運!