我有以下课程:
export class SomeModel {
prop1: number;
prop2: number;
comment: string;
}
和以下方法来动态获取其属性:
getTypeProperties<T>(obj: T): string[] {
const ret: string[] = [];
for (const key in obj) {
if (obj.hasOwnProperty(key))
ret.push(key);
}
return ret;
}
以下调用返回一个空数组:
getTypeProperties(new SomeModel());
但是,如果我使用null
显式初始化所有属性,则将正确返回属性:
export class SomeModel {
prop1: number = null;
prop2: number = null;
comment: string = null;
}
问题:这是正常行为吗?还是有一个TypeScript编译器开关可以对此进行切换?
我不知道它是否相关,但这是tsconfig.json的内容:
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
]
}
}
答案 0 :(得分:1)
这是设计使然,字段声明不输出任何JavaScript代码,它们只是告诉编译器该字段存在(即,当我在代码中使用它时,应该不会抱怨),并且是某种类型。在您首次分配该字段之前,该字段将不存在于实例上,因此不会被迭代。如果初始化该字段,则其值将分配给构造函数中的实例,从而变得可迭代。
您已经发现解决此问题的最简单方法是,如果只有值undefined
,则为该字段分配一个值。
我们可以在为ES5生成的代码中看到此行为。例如对于此类
class A {
nonInitField: number;
initField = 0;
test() {
this.nonInitField = 0;// Can be used, and will be iterable after it is assigned
}
}
此代码生成:
var A = /** @class */ (function () {
function A() {
this.initField = 0; // Iterable right away as it is assigned in the constructor
}
A.prototype.test = function () {
this.nonInitField = 0; // Can be used, and will be iterable after it is assigned
};
return A;
}());