在角度6中,我有一个这样的打字稿类
export class Hello {
id: number;
name?:string;
txt?:string;
}
我想从组件控制器中检索具有属性名称的数组,而无需创建对象。像这样:
ObjectType.keys(Hello);
// ["id", "name", "txt"]
有可能吗?
答案 0 :(得分:2)
我相信这是不可能的,但是如果您声明属性为static然后通过直接引用
这样的类进行访问,那将是可能的 class Hello{
static id: number;
static name?:string;
static txt?:string;
}
Hello.id;
显然,另一种方法是通过将构造函数放入对象并使用默认值初始化来创建对象
答案 1 :(得分:2)
如果未初始化字段,即使创建对象也不会检索该类的所有成员。如果仅声明了一个字段,则编译器将知道它并提供类型检查,但不会为此发出任何代码,因此,如果您使用Object.keys
,则只会检索分配了值的字段。
一个选择是仅创建一个具有与原始字段相同的所有字段的对象(减去方法),并获得该对象的密钥。我们可以让编译器检查该对象是否具有与该类完全相同的字段,且不多也不少。因此,如果更改该类,则如果忘记更改该对象,则会收到错误消息。
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
});
我们甚至可以将这种方法扩展到创建一个对象,该对象也具有有关属性的类型信息,这再次迫使编译器检查该对象是否正确。对于基本类型,我们将传递表示类型名称的字符串,对于对象属性,我们可以传递类构造函数,也可以传递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'
});
答案 2 :(得分:0)
不,类属性会被转换为类似这样的内容:
class Hello {
constructor() {
this.id = "";
}
}
因此,它们仅在构造后的对象实例上存在,而不在类本身上存在。