Búsqueda de sitios web

typescript - Verificando la firma de la función


Estoy trabajando en un proyecto de localizador de servicios y espero que se pasen funciones que requieran un solo parámetro.

Aquí hay un fragmento:

"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];
    }
}

Sin embargo, cuando intento compilar esto obtengo el siguiente error:

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

Intenté crear un nuevo tipo:

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

Y traté de cambiar instanceof Function a instanceof ServiceFunction, pero entonces obtengo el siguiente error:

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

He buscado por todas partes pero no he podido encontrar ningún ejemplo de cómo verificar si una función pasada coincide con una firma especificada.

Respuesta #1

La solución más simple es usar una variable y dejar que TypeScript infiera su tipo:

    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
    }

Como alternativa, es posible envolver la condición en una guardia de tipo explícita:

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

Un pequeño aviso: El tipo Object | Function no es elegante. Puede considerar usar un tipo de función mejor y/o un tipo de objeto mejor.

Respuesta #2

Aquí hay una solución más simple que la de Paleo. En lugar de usar instanceof Function, puedes usar typeof f === 'function'. Haz clic aquí para un ejemplo que he creado en el playground de TypeScript. Si pasas el cursor sobre la variable input en las dos ramas if, verás el resultado que deseas.

Artículos relacionados