Неинициализированные свойства класса TypeScript не повторяются - PullRequest
0 голосов
/ 27 июня 2018

У меня есть следующий класс:

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"
    ]
  }
}

1 Ответ

0 голосов
/ 27 июня 2018

Это сделано специально, объявления полей не выводят никакого кода 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;
}());
...