问题:
In angular 6, I have a typescript class like this
export class Hello {
id: number;
name?:string;
txt?:string;
}
From a component controller, I would like to retr...
可以将文章内容翻译成中文,广告屏蔽插件会导致该功能失效:
问题:
In angular 6, I have a typescript class like this
export class Hello {
id: number;
name?:string;
txt?:string;
}
From a component controller, I would like to retrieve an array with the property names, without needing to create an object. Something like:
ObjectType.keys(Hello);
// ["id", "name", "txt"]
Is that possible ?
回答1:
i believe this is not possible but what is possible if you declare the property static and then access with direct reference of class like
class Hello{
static id: number;
static name?:string;
static txt?:string;
}
Hello.id;
obviously the other way is creating object by putting constructor in it and initialization with default value,
回答2:
If the fields are not initialized even creating an object will not retrieve all members of the class. If a field is just declared, the compiler will know about it and offer type checking but it will not emit any code for it, so if you use Object.keys
only field that were assigned a value will be retrieved.
One option is to just create an object with all the same fields as the original (minus methods) and get the keys if this object. We can get the compiler to check that this object will have exactly the same fields as the class, no more and no less, so if we change the class we will get an error if we forget to change this object as well.
export class Hello {
id: number;
name?: string;
txt?: string;
method() { }
}
type NonMethodKeys<T> = { [P in keyof T]: T[P] extends Function ? never : P }[keyof T];
function getFields<T>(fields: { [P in NonMethodKeys<T>]: true }) {
return Object.keys(fields)
}
getFields<Hello>({
id: true,
name: true,
txt: true // if we comment this out we would get an error
//noAProp : true; //this would be an error
});
We can even extend this approach to creating an object that also has type information about the properties, again forcing the compiler to check that the object is accurate. For primitive types, we will pass a string representing the type name, for object properties we can either pass in the class constructor or just object
:
interface IProp { }
export class Hello {
id: number;
name?: string;
txt?: string;
subHi: Hello;
prop: IProp;
method() { }
}
type NonMethodKeys<T> = { [P in keyof T]: T[P] extends Function ? never : P }[keyof T];
type TypeOf<T> = T extends boolean ? 'boolean' :
T extends string ? 'string' :
T extends number ? 'number' :
'object' | (new (...args: any[]) => T);
function getFields<T>(fields: { [P in NonMethodKeys<T>]: TypeOf<T[P]> }) : typeof fields{
return fields
}
let fields = getFields<Hello>({
id: 'number',
name: 'string',
txt: 'string',
subHi: Hello,
prop: 'object'
});
回答3:
No, class properties are transpiled to something like this:
class Hello {
constructor() {
this.id = "";
}
}
Therefore they only exist on an object instance after it was constructed, not on the class itself.