Búsqueda de sitios web

firma - Función de TypeScript que devuelve un conjunto de funciones


Estoy intentando portar el siguiente código de JS puro a TypeScript para definir mejor los tipos de retorno de todas las funciones. Este código exporta una única función, resource. Cuando se llama, resource devuelve un objeto que contiene otras funciones.

Parece que la firma del tipo desaparece al usar el recurso en la clase Demo, inicializado en el constructor. Un enfoque para esto sería definir una interfaz para resource. Sin embargo, no parece que pueda definir una interfaz para resource sin repetir los parámetros que ya están definidos en doThingOne() y doThingTwo(). Todos mis intentos actuales me han llevado a tener que duplicar las firmas. ¿Cómo debería abordar esto para mantener las cosas DRY?

function resource(someVar) {

    function doThingOne(p1 = '') {
        return Promise.resolve('thing one ' + someVar + p1);
    }

    function doThingTwo(p1 = '') {
        return Promise.resolve('thing two ' + someVar + p1);
    }

    return {
        doThingOne,
        doThingTwo
    };
}

class Demo {
    resource1;

    constructor() {
        this.resource1 = resource('resource1');
    }
}

const issues = new Demo();
issues.resource1 // no type information for resource1

Respuesta #1

Básicamente quieres declarar un miembro como el tipo de resultado de una función.

La forma más sencilla de hacer esto sería dejar que el compilador lo infiera en función de la asignación:

class Demo {
    constructor(name: string, public resource1 = resource(name)) {

    }
}

const issues = new Demo("resource1");
issues.resource1 // correct type

Si esto no es práctico, puede obtener el tipo de retorno de una de dos maneras:

En Typescript 2.8

Usa el tipo condicional ReturnType<T>. (2.8 no está lanzado al momento de escribir esto, pero será lanzado en marzo de 2018, puedes obtenerlo mediante npm install -g typescript@next)

class Demo {
    public resource1: ReturnType<typeof resource>
    constructor() {

    }
}

Pre 2.8

Puedes extraer el tipo de la función usando una función auxiliar y una variable ficticia:

// Dummy function, just used to extract the result type of the function passed as the argument
function typeHelper<T>(fn: (...p:any[]) => T): T{
    return null as T;
}
// Dummy variable, null at runtime, but it's type is inferred as the result of the `resource function
let dummy = typeHelper(resource);

// Create a type definition based on the type of dummy
type resourceReturnType = typeof dummy;


class Demo {
    public resource1: resourceReturnType
    constructor() {

    }
}

Respuesta #2

No hay necesidad de una función de fábrica una vez que existe una instancia de clase que puede mantener estado (que es someVar en el caso de la función resource):

class Resource {
    constructor(private someVar: string);

    doThingOne(p1 = '') {
        return Promise.resolve('thing one ' + this.someVar + p1);
    }

    doThingTwo(p1 = '') {
        return Promise.resolve('thing two ' + this.someVar + p1);
    }
}

class Demo {
    resource1 = new Resource('resource1');
}

Pueden ser refactorizados a una sola clase si Demo no se supone que haga otra cosa.

Artículos relacionados