2017-02-27 39 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变量上,您将看到所需的结果。