Búsqueda de sitios web

javascript - Propagar la firma del constructor al método de fábrica


Estoy intentando determinar un método para crear una función fábrica de manera genérica de tal manera que pueda pasarle una clase y recibir de vuelta una función que creará instancias de esa clase. Algo similar a:

function createClassFactory<T> (MyClass: {new(...):T}) {
    return function classFactory(...) {
        return new MyClass(...)
    }
}

Para mantener la información de tipo, me gustaría que classFactory tuviera la misma firma que el constructor de MyClass. En este momento no se me ocurre cómo podría ser posible.

¿Es este tipo de cosa posible de otra manera?

Respuesta #1

No puedo pensar en una manera de hacer lo que quieres (al menos no de manera elegante), a menos que estés dispuesto a aceptar todos los parámetros del constructor como un solo objeto.
Si todas las clases esperan un solo objeto como parámetros, entonces puedes forzar una interfaz sobre esos objetos de propiedades y usando genéricos puedes lograr lo que buscas (bueno, casi):

class Base<T> {
    constructor(props: T) {}
}

type BaseConstructor<C extends Base<P>, P> = {
    new(props: P): C; 
}

interface AProps {}

class A extends Base<AProps> {}

interface BProps {
    x: number;
    y: number;
}

class B extends Base<BProps> {}

interface CProps {
    str: string;
    ok?: boolean;
}

class C extends Base<CProps> {}

function createClassFactory<C extends Base<P>, P> (MyClass: BaseConstructor<C, P>) {
    return function classFactory(props: P) {
        return new MyClass(props);
    }
}

// the following are valid:
let a1 = createClassFactory(A)({});
let b1 = createClassFactory(B)({ x: 3, y: 5 });
let c1 = createClassFactory(C)({ str: "stirng" });
let c2 = createClassFactory(C)({ str: "stirng", ok: true });

// these aren't:
let b2 = createClassFactory(B)({ x: 3, y: "5" });
let c3 = createClassFactory(C)({ ok: true });

// but this one is:
let a2 = createClassFactory(A)({ key: "value" });

(código en el área de juegos)

Digo casi debido al último ejemplo donde a2 se crea con un objeto no vacío.
Pero aparte de eso, creo que es prácticamente lo que pediste.

Artículos relacionados