How do I achieve the following prototype-code:
class test {
a: number;
b: boolean;
c: string;
}
for (const so in test)
so, //'a', 'b', 'c'...
//so.type //'number', 'boolean', 'string'...
I don't have any idea how to get the type however I tried creating a new object and iterating over it for the names but obviously this didn't work since the class members were left uninitialized.
As suggested in the comment on the question, metadata could be used to some degree but it is messy.
First the decorator has to store all key names in a list because the properties do not actually exist on the prototype:
import 'reflect-metadata';
const propertiesSymbol = Symbol('properties');
const metadata = (target: any, key: string) => {
let list = <string[] | undefined>target[propertiesSymbol];
if (list == undefined)
list = target[propertiesSymbol] = [];
list.push(key);
};
This is used on the properties of the class:
class Test {
@metadata
a!: number;
@metadata
b!: boolean;
@metadata
c!: string;
}
To iterate the list can be retrieved from the symbol properties symbol slot and the getMetadata
function can be used to get the generated design:type
. This will be the type constructor, not the name.
for (const key of (Test.prototype as any)[propertiesSymbol])
console.log(Reflect.getMetadata("design:type", Test.prototype, key));
This should print something like:
[Function: Number]
[Function: Boolean]
[Function: String]
Note that the compiler settings have to contain decorators & metadata flags:
"compilerOptions": {
// ...
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}