Получить все доступные свойства класса

#typescript #typescript-generics

#typescript #typescript-обобщения

Вопрос:

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

 class A {
  id: number
  propertyA: string

  constructor(id: number) {
    this.id = id
  }
}

let a = new A(3)

console.log(SomeFunction(a))
// expected output = ['id', 'propertyA']
  

В принципе, когда я создавал экземпляр A, я не задавал значение для PropertyA. При SomeFunction(a) вызове он должен возвращать все свойства, которые могут быть у класса A, включая propertyA даже если оно не было задано.

Object.getPropertyNames(a) возвращает только ['id']

Каким должен быть код someFunction?

Ответ №1:

Если вы не зададите значение для свойства, оно не будет существовать в объекте. Во время выполнения нет доступных метаданных, в которых говорилось бы «Это свойство объявлено, но ему никогда не назначалось».

Вам нужно будет выбрать значение по умолчанию для propertyA и установить его (возможно, в инициализаторе объявления), если вы хотите убедиться, что каждый экземпляр A обладает этим свойством.

Например, если вы не используете строгие проверки на нуль, вы могли бы сделать это:

 class A {
  id: number
  propertyA: string = undefined

  constructor(id: number) {
    this.id = id
  }
}
  

Это означает, что new A(42).propertyA будет по-прежнему предоставлять значение undefined (как это происходит с вашим существующим A классом), но свойство будет фактически существовать, и поэтому SomeFunction его можно будет найти.

Живая копия:

 class A {
  id /* : number*/
  propertyA /*: string*/ = undefined

  constructor(id/*: number*/) {
    this.id = id
  }
}
console.log(Object.getOwnPropertyNames(new A(42)));  

Если вы используете строгие проверки на нуль, вам нужно будет инициализировать его в виде строки.

Комментарии:

1. Ах… Я так и подозревал. Спасибо за разъяснение

Ответ №2:

Пока значение свойства не задано, оно не будет существовать в экземпляре класса.

Здесь мы можем перечислять оба id и propertyA , но только тогда, когда они установлены:

 function showProps(obj) {
  return Object.keys(obj);
}

class A {
  constructor(id, propA) {
    this.id = id;
    if (propA)
      this.propertyA = 0;
  }
}

const a = new A(3);
const b = new A(3, 1);

console.log(showProps(a));
console.log(showProps(b));  

Комментарии:

1. «…как только он скомпилирован в JavaScript, он исчезает». Это зависит от того, на какую версию JavaScript у вас настроен tsc, поскольку class fields находится на продвинутой стадии (общедоступные поля включены по умолчанию в версии Chrome 8, например) и почти наверняка появятся в ближайшие месяцы, а значит, войдут в спецификацию 2020.

2. @T.J. Crowder, большое спасибо за точность, я обновлю свой ответ.