javascript - Crear un tipo derivado de una clase, pero omitir el constructor (typescript)
Tengo una interfaz y una clase definidas así:
interface Foo {
constructor: typeof Foo;
}
class Foo {
static bar = 'bar';
constructor(data: Partial<Foo>) {
Object.assign(this, data);
}
someMethod() {
return this.constructor.bar;
}
prop1: string;
prop2: number;
}
La interfaz es necesaria para que this.constructor tenga un tipo fuerte. Sin embargo, rompe mi capacidad de pasar un objeto simple al constructor de la clase:
const foo = new Foo({ prop1: 'asdf', prop2: 1234 });
// Argument of type '{ prop1: string; prop2: number; }' is not assignable to parameter of type 'Partial<Foo>'.
// Types of property 'constructor' are incompatible.
// Type 'Function' is not assignable to type 'typeof Foo'.
// Type 'Function' provides no match for the signature 'new (data: Partial<Foo>): Foo'.
Entiendo el mensaje de error, pero no sé cómo solucionarlo. ¿Hay alguna manera de tener un Partial<Foo> que me permita pasar un objeto simple? Aquí hay un ejemplo:
Parque infantil
Respuesta #1
Aquí está el tipo real que crea un tipo derivado de una clase omitiendo el constructor (como en el título de la pregunta) y manteniendo los métodos habituales:
type NonConstructorKeys<T> = ({[P in keyof T]: T[P] extends new () => any ? never : P })[keyof T];
type NonConstructor<T> = Pick<T, NonConstructorKeys<T>>;
Uso con el Foo de la pregunta:
type FooNonConstructorKeys = NonConstructorKeys<Foo>; // "prop1" | "prop2" | "someMethod"
type FooNonConstructor = NonConstructor<Foo>;
Respuesta #2
Terminé encontrando lo que necesitaba en esta maravillosa respuesta:
cómo eliminar propiedades mediante un tipo mapeado en TypeScript
El código en esa respuesta crea un tipo derivado que contiene solo métodos. Yo necesitaba hacer lo inverso de eso. El siguiente ayudante NonMethods<T> crea un tipo derivado con todos los métodos eliminados.
type NonMethodKeys<T> = ({[P in keyof T]: T[P] extends Function ? never : P })[keyof T];
type NonMethods<T> = Pick<T, NonMethodKeys<T>>;
Aquí está el patio de recreo
