I've got a .ts file which contains many classes like below (Angular Project). The Classes auto generated from backend classes.
export class User {
name: string;
lastName: number;
userCode: string;
}
Now, I want to read this class and its properties by its name. Then I will create the Angular input elements with this data.
For Instance (pseudo code):
let className = 'User';
let listOfProperties = reflectObject(className)
Javascript is a prototype based language, so it differs from Java and C# which are class based. You need an instance of the class to get it's properties. You will also not be able to read any properties that have not been instantiated.
So, classes will need default values for all properties (any value will do), then you will need to call the constructor of the class, and finally you can read its properties.
eval() will let you execute a string as javascript.
// Any default value is fine
export class User {
name = '';
lastName = null;
userCode = undefined;
}
let className = 'User';
let instance = eval('new ' + className + '()');
let properties = Object.getOwnPropertyNames(instance);
console.log(properties); // Array(3) [ "name", "lastName", "userCode" ]
You could also just memoize the properties in an object.
// Any default value is fine
export class User {
name = '';
lastName = null;
userCode = undefined;
}
let classProperties: {[key: string]: string[]} = {
'User': Object.getOwnPropertyNames(new User())
};
let className = 'User';
let properties = classProperties[className];
console.log(properties); // Array(3) [ "name", "lastName", "userCode" ]
The nice thing about this method is that you can call Object.getOwnPropertyNames(classProperties) to get a list of all valid classes.
If you can't provide default values for the properties then you need to hardcode the property names. There's no way for JS to know about properties that aren't there as far as I know.
let classProperties: {[key: string]: string[]} = {
'User': [ "name", "lastName", "userCode" ]
};
let className = 'User';
let properties = classProperties[className];
console.log(properties); // Array(3) [ "name", "lastName", "userCode" ]
Although if the classes are being auto generated from the backend (whatever that means), then I think it would make more sense for your backend to provide a list of properties.
As Chris Hamilton noted, there is no way to do that in native JavaScript/TypeScript.
But You can use tst-reflect for example. It is a TypeScript transformer plugin generating metadata about types for runtime usage and it has working generics too.
Your example let listOfProperties = reflectObject(className) would be eg.
import { getType, Type } from 'tst-reflect';
class User {
name = '';
lastName = null;
userCode = undefined;
}
const userType: Type = getType<User>();
const listOfProperties = userType.getProperties().map(prop => `${prop.name}: ${prop.type.name}`);
Check out this demo on StackBlitz.