Typescript - retrieving class attributes without creating object

问题: 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.

  • 发表于 2018-07-05 15:31
  • 阅读 ( 279 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除