Búsqueda de sitios web

javascript - ¿Puede una clase de Typescript implementar una interfaz invocable?


Las interfaces de Typescript permiten la definición de una firma de llamada en estilo función de la siguiente manera:

interface A {
    (x: number): number;
}

Esto se puede implementar, por ejemplo, con una función:

const a: A = function(x: number): number {
    return 1;
}

¿Es posible implementar tal interfaz usando una clase?

Lo he intentado así:

class B implements A {
    (x: number): number {
        return 1;
    }
}

Pero recibo este error:

La clase 'B' implementa incorrectamente la interfaz 'A'. El tipo 'B' no proporciona ninguna coincidencia para la firma '(x: number): number'.ts(2420)

¿Hay alguna manera de implementar este tipo de interfaz usando una clase en Typescript?

Respuesta #1

Esto es posible. En mis proyectos implementé una clase auxiliar Callable combinada con una interfaz con el mismo nombre. La combinación con la interfaz es necesaria para darle a TypeScript las tipificaciones correctas de la firma de la función:

export interface Callable<T extends unknown[] = unknown[], R = unknown> {
    (...args: T): R;
}

export class Callable<T extends unknown[] = unknown[], R = unknown> extends Function {
    public constructor(func: (...args: T) => R) {
        super();
        return Object.setPrototypeOf(func, new.target.prototype) as typeof this;
    }
}

Usar esta clase es bastante sencillo:

class Test extends Callable<[ number, number ], number> {
    public multiplier = 2;

    public constructor() {
        super((a, b) => (a + b) * this.multiplier);
    }
}

const test = new Test();
console.log(test(1, 2)); // Prints 6
test.multiplier = 3;
console.log(test(1, 2)); // Prints 9

Algunas explicaciones:

  • Defines los tipos de los argumentos de la función en el primer parámetro de tipo en forma de un array. [ number, number] en este caso significa que la función espera dos parámetros numéricos.
  • Defines el tipo de retorno de la función como segundo parámetro de tipo. En este caso, esto es nuevamente number.
  • Pasas la función real que se llama al invocar la instancia de la clase como una función al constructor de la superclase Callable.

Artículos relacionados