¿Cómo puedo escribir correctamente una función que devuelve una clase en TypeScript?
En TypeScript, la palabra clave class introduce tanto un valor como un tipo:
class Plain { };
const plain: Plain = new Plain();
¿Hay una manera de crear una función que devuelva algo que sea tanto un tipo como un valor?
Otra forma de hacer esta pregunta es: ¿hay una manera de declarar el tipo de createClass a continuación para que const a2: Animal=new Animal() pase la verificación de tipos?
declare function createClass<T extends string>(t: T): (new () => { type: T });
const Animal = createClass("animal");
const a1 = new Animal();
const a2: Animal = new Animal(); // Error: 'Animal' refers to a value, but is being used as a type here.
const a3: InstanceType<typeof Animal> = new Animal(); // OK but verbose, even if I make a type alias
Ver este Playground de TypeScript
Respuesta #1
Una declaración de clase produce tanto un tipo como un valor. El valor es el constructor de la clase (por esto, cuando escribes new Plain() en expresiones, invocas el constructor). El tipo, tiene el mismo nombre que la clase y representa el tipo de instancia de la clase (por esto puedes usarlo en anotaciones de tipo).
Un const, por otro lado, es solo un valor, incluso si contiene una clase. No hay un tipo correspondiente. La única manera de lograr una funcionalidad similar a la declaración de clase es crear un alias de tipo con el mismo nombre.
declare function createClass<T extends string>(t: T): (new () => { type: T });
const Animal = createClass("animal");
type Animal = InstanceType<typeof Animal>
const a1 = new Animal();
const a2: Animal = new Animal();
El valor y el tipo residen en dominios diferentes, así que usar el mismo nombre está bien.
Desafortunadamente, no hay manera de hacer esto en una sola instrucción, implica un poco de verborrea.
