I'm working on a service locator project and I'm expecting functions to be passed in that require a single parameter.
Here's a snippet:
"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];
}
}
However, when I try to compile this I get the following error:
error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'ServiceDeclaration' has no compatible call signatures.
I tried creating a new type:
type ServiceFunction = (container: Pimple) => any;
And tried changing instanceof Function
to instanceof ServiceFunction
but then I get the following error:
error TS2693: 'ServiceFunction' only refers to a type, but is being used as a value here.
I've looked around but haven't been able to find any examples of checking if a passed in function matches a specified signature.
The simplest solution is to use a variable and let TypeScript infer its type:
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
}
As an alternative, it is possible to wrap the condition in an explicit type guard:
function isFunction(f): f is Function {
return f instanceof Function;
}
A small notice: The type Object | Function
is not elegant. You may consider to use a better function type and / or a better object type.
Here is a simpler solution than that of Paleo. Instead of using instanceof Function
, you can use typeof f === 'function'
. Click here for an example I've created on the TypeScript playground. If you mouse over the input
variable in the two if
branches, you'll see the result that you want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With