typescript1.5 - TypeScript 1.5, reflexión y decorador
Me preguntaba si era posible usar reflexión, y más particularmente reflexión de clase con respecto a un decorador, en una propiedad, en un parámetro o en un método?
¿Es posible usar un reflector para obtener la información utilizada en los decoradores?
Si es posible, ¿cómo podemos hacer eso? Si no, ¿por qué no podemos hacer eso?
EDITAR :
Tengo una aplicación en la que uso decoradores, para inyectar datos, desde un serviceRegistry, a un decorador llamado @Inject.
En esta aplicación, lleno un registro de servicios simple a mano, como:
serviceRegistry.push(MyClass1)
serviceRegistry.push(MyClass2)
...
serviceRegistry.push(MyClass100)
El objetivo es poder llenar este registro de servicios con clases que estén decoradas con la anotación @ToInject, en tiempo de ejecución.
Esto me permitirá evitar llenar este registro a mano y automatizar esto de manera sencilla.
Gracias de antemano
Respuesta #1
Puedes usar la reflexión importando el paquete reflect-metadata.
import 'reflect-metadata';
Úsalo con TypeScript 1.5 y la bandera del compilador emitDecoratorMetadata configurada en true. No olvides incluir también una referencia a reflect-metadata.d.ts.
Necesitas implementar tus propios decoradores:
// declare property decorator
function logType(target : any, key : string) {
var t = Reflect.getMetadata("design:type", target, key);
console.log(`${key} type: ${t.name}`);
}
class Demo{
@logType // apply property decorator
public attr1 : string;
}
Se registrará en la consola:
attr1 type: String
Otro ejemplo:
// declare parameter decorator
function logParamTypes(target : any, key : string) {
var types = Reflect.getMetadata("design:paramtypes", target, key);
var s = types.map(a => a.name).join();
console.log(`${key} param types: ${s}`);
}
class Foo {}
interface IFoo {}
class Demo{
@logParameters // apply parameter decorator
doSomething(
param1 : string,
param2 : number,
param3 : Foo,
param4 : { test : string },
param5 : IFoo,
param6 : Function,
param7 : (a : number) => void,
) : number {
return 1
}
}
Se registrará en la consola:
doSomething param types: String, Number, Foo, Object, Object, Function, Function
Nota que las interfaces IFoo y el literal de objeto { test : string} se serializan como Object. Las reglas de serialización son:
numberserializado comoNumberstringserializado comoStringbooleanserializado comoBooleananyserializado comoObjectvoidse serializa comoundefinedArrayserializado comoArray- Si un
Tuple, serializado comoArray - Si una
classlo serializara como el constructor de la clase - Si un
Enumlo serializara comoNumber - Si tiene al menos una firma de llamada, serializada como
Function - De lo contrario, serializado como
Object(Incluyendo interfaces)
Las interfaces y los literales de objetos pueden ser serializados en el futuro mediante la serialización de tipos complejos, pero esta función no está disponible en este momento.
También puedes obtener el tipo de retorno de una función usando:
Reflect.getMetadata("design:returntype", target, key);
Si necesitas más información sobre los decoradores, puedes leer: Decoradores y reflexión de metadatos en TypeScript: De novato a experto
