Cuando el código fuente se compila de mecanografiado a javascript, las anotaciones de tipo se eliminan y no hay forma de verificar el tipo de una variable en tiempo de ejecución.
Sin embargo, hay muchas bibliotecas de mecanografiados que parecen cambiar el comportamiento en función de las anotaciones de tipo de las propiedades de la clase. Por ejemplo, al escribir entidades typeorm, podríamos escribir algo como:
@Entity() class MyEntity extends BaseEntity { @Field() public id: number // automatically infers int database type @Field() public description: string // automatically infers varchar or text database type @Field() public image: string | null // cannot infer correct type, will throw error }También tenemos algo similar con typedi (pasa la referencia correcta a través del constructor), type-graphql (construye el esquema de graphql con el tipo de graphql correcto), etc. Lo entiendo cuando tienes que pasar una función a través de un decorador o algo similar, pero ¿cómo hacer esto? ¿Las bibliotecas infieren tipos solo a partir de anotaciones de tipo?
Sentí curiosidad y encontré la respuesta en la documentación de TypeORM aquí :
Configuración de mecanografiado
Además, asegúrese de estar utilizando TypeScript versión 4.5 o superior, y de haber habilitado las siguientes configuraciones en
tsconfig.json:"emitDecoratorMetadata": true, "experimentalDecorators": true,
Sospeché que le dije a TypeScript que proporcionara información de tipo de tiempo de ejecución a los decoradores y, de hecho, lo hace :
Emitir metadatos de decorador
emitDecoratorMetadataHabilita el soporte experimental para emitir metadatos de tipo para decoradores que funcionan con el módulo
reflect-metadata.
Cuando tiene eso habilitado, TypeScript emite llamadas a los decoradores que incluyen información de tipo en tiempo de ejecución. El ejemplo en la documentación es para este código:
class Demo { @LogMethod public foo(bar: number) { // do nothing } }
... que emite funciones __decorate y __metadata , luego esto:
class Demo { foo(bar) { // do nothing } } __decorate([ LogMethod, __metadata("design:type", Function), __metadata("design:paramtypes", [Number]), __metadata("design:returntype", void 0) ], Demo.prototype, "foo", null);
Si miramos tu ejemplo, esto es lo que emite para las llamadas al decorador:
__decorate([ Field(), __metadata("design:type", Number) ], MyEntity.prototype, "id", void 0); __decorate([ Field(), __metadata("design:type", String) ], MyEntity.prototype, "description", void 0); __decorate([ Field(), __metadata("design:type", Object) ], MyEntity.prototype, "image", void 0); MyEntity = __decorate([ Entity() ], MyEntity);