I have a typescript classes:
class InnerClassA {
property1: string;
property2: number;
}
class InnerClassB {
property3: boolean;
property4: string;
}
class ABC {
innerA: InnerClassA;
innersB: InnerClassB[];
}
Now I want to add some metadata to the properties.
For this I create a decorator:
import 'reflect-metadata';
export const metadataKey = 'label';
export function Label(label: string): PropertyDecorator {
return function (target: any, propertyKey: string) {
Reflect.defineMetadata(metadataKey, label, target, propertyKey);
};
}
And then I apply this decorator:
class InnerClassA {
@Label('Name')
property1: string;
@Label('Age')
property2: number;
}
class InnerClassB {
@Label('Has a cat')
property3: boolean;
@Label('Cat name')
property4: string;
}
class ABC {
@Label('General info')
innerA: InnerClassA;
@Label('Pets')
innersB: InnerClassB[];
}
Now I have data that comes from the backend and I need to do transformation:
interface TreeNode {
label: string;
data: Array<TreeNode | LeafNode>;
}
interface LeafNode {
label: string;
value: any;
}
function transformObjectToTree(obj: any): Array<TreeNode | LeafNode> {
const result: Array<TreeNode | LeafNode> = [];
for (const [key, value] of Object.entries(obj)) {
const label = Reflect.getMetadata(
metadataKey,
InnerClassA.prototype, // TODO: Problem is here, should be for each class
key,
);
if (typeof value === 'object' && value !== null) {
const subtree: TreeNode = {
label: label || key,
data: transformObjectToTree(value),
};
result.push(subtree);
} else {
const leaf: LeafNode = {
label: label || key,
value: value,
};
result.push(leaf);
}
}
return result;
}
The problem is that I need to pass a target to the Reflect.getMetadata method, but I can't get it in runtime.
const data: ABC = this.service.getData();
const result = transformObjectToTree(data);
I tried these options:
const target = Reflect.getPrototypeOf(obj); // No luck
const target = Object.getPrototype(obj); // No luck
const target = obj.prototype; // No luck
const target = obj.__proto__; // No luck
const data: ABC = {
innerA: {
property1: "Mary",
property2: "42",
},
innerB: [
{
property3: true,
property4: "Jack",
},
{
property3: true,
property4: "Jim"
}
]
};
const result = transformObjectToTree(data);
with the result:
[
{
"label": "General info",
"data":
[
{ "label": "Name", "value": "Mary" },
{ "label": "Age", "value": 42 }
]
},
{
"label": "Pets"
"data":
[
{
"label": "0",
"data":
[
{ "label": "Has a cat", "value": true },
{ "label": "Cat name", "value": "Jack" }
]
},
{
"label": "1",
"data":
[
{ "label": "Has a cat", "value": true },
{ "label": "Cat name", "value": "Jim" }
]
}
]
}
]
How to workaround it?