2017-02-27 40 views
2

我正在開發一個服務定位器項目,並期待函數能夠被傳遞,需要一個參數。檢查函數簽名

這裏有一個片段:

"use strict"; 

/** Declaration types */ 
type ServiceDeclaration = Function|Object; 

export default class Pimple { 

    /** 
    * @type {{}} 
    * @private 
    */ 
    _definitions: {[key: string]: ServiceDeclaration} = {}; 

    /** 
    * Get a service instance 
    * @param {string} name 
    * @return {*} 
    */ 
    get(name: string): any { 
     if (this._definitions[name] instanceof Function) { 
      return this._definitions[name](this); 
     } 
     return this._definitions[name]; 
    } 
} 

然而,當我嘗試編譯此我得到以下錯誤:

error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'ServiceDeclaration' has no compatible call signatures. 

我試圖創建一個新的類型:

type ServiceFunction = (container: Pimple) => any; 

並試圖更改instanceof Functioninstanceof ServiceFunction,但後來我得到以下錯誤:

error TS2693: 'ServiceFunction' only refers to a type, but is being used as a value here. 

我環顧四周,但一直未能找到任何檢查傳遞的函數是否匹配指定簽名的示例。

回答

4

最簡單的解決方案是使用一個變量,並讓打字稿推斷其類型:

get(name: string): any { 
     let f = this._definitions[name]; // here, 'f' is of type Function|Object 
     if (f instanceof Function) 
      return f(this);    // here, 'f' is of type Function 
     return f;      // here, 'f' is of type Object 
    } 

作爲替代方案,能夠以包裹條件中顯式type guard

function isFunction(f): f is Function { 
    return f instanceof Function; 
} 

甲小通知:類型Object | Function不是優雅。你可以考慮使用更好的function type和/或更好的object type

+1

謝謝。我測試了幾個變體,發現關鍵部分是先賦值'let f = this._definitions [name];'然後檢查並使用局部變量。我不需要外部函數,我可以做'if(f instanceof Function){return f; }' –

+1

@AndrewShell你說得對。我編輯過。 – Paleo

1

這是一個比Paleo更簡單的解決方案。而不是使用instanceof Function,您可以使用typeof f === 'function'。點擊here查看我在TypeScript操場上創建的示例。如果將鼠標懸停在兩個if分支中的input變量上,您將看到所需的結果。