Методы получения для десериализованных объектов в Typescript - PullRequest
0 голосов
/ 13 декабря 2018

У нас есть множество Http-вызовов к нашим службам, которые возвращают коллекцию объектов.В нашем угловом приложении typcript интерпретирует их в соответствующий тип, если он указан, например Person:

export class Person{
  public firstName: string;
  public lastName: string;
  public salutation: string;
}

Допустим, я хочу иметь возможность легко создать строку приветствия для этого пользователя, но я хочу бытьхороший программист и делать это один раз вместо нескольких мест.Поэтому я создаю метод получения, который будет его извлекать:

export class Person{
  public firstName: string;
  public lastName: string;
  public salutation: string;
  public get greeting(): string {
      return salutation + " " + firstName + " " + lastName;
  }
}

Однако при десериализации его машинописью отсутствует прототип свойства приветствия (для него установлено значение undefined).Я получаю, что машинописный текст отображает объект JSON на класс, который у него есть, и любые отсутствующие поля / свойства не существуют в сопоставленном объекте (при вызове возвращается значение undefined).Какой лучший способ исправить это?

В качестве примера того, как мы вызываем службу:

this.authHttp.post(this.url, user, params).then(
  (res: Person) => {
      console.log(res);
      console.log(res.greeting);
  }
);

Ответы [ 3 ]

0 голосов
/ 13 декабря 2018

То, что вы работали по стечению обстоятельств , поскольку имена свойств, к которым вы обращались, также были предоставлены в ответе от .post.На самом деле TypeScript больше не используется после команды tsc, которая переносит его в исходный код JavaScript.Из-за этого вы теряете все проверки типов во время выполнения.

Если вы жестко закодируете это назначение, например, так:

let me: Person = { firstName: 'Ian', lastName: 'MacDonald', salutation: 'Hello.' };

вы получите ошибку TypeScript при попыткедля создания JavaScript.

Property 'greeting' is missing in type
    '{ firstName: string; lastName: string; salutation: string; }'
    but required in type 'Person'.ts(2741)

Та же ошибка будет появляться и для любых функций, которые вы определили в своем классе.Это потому, что { ... } это не ваш тип;он имеет только то, что явно определено.То, что происходит в ответ на ваш сервер, будет подчиняться тем же правилам назначения, но проблема не будет присутствовать (потому что данные отсутствуют) до времени выполнения.

Я рекомендую использовать канал длясоздайте себе экземпляр своего класса, прежде чем что-либо попытается использовать ответ сервера, чтобы любые ошибки могли быть обнаружены при первом контакте, а не через 10 секунд, когда вы наконец попытаетесь получить доступ к действию .save(), которое не существует.

.post(...).pipe(map((incoming: any) => {
  let person: Person = new Person();
  person.firstName = incoming.firstName;
  person.lastName = incoming.lastName;
  person.salutation = incoming.salutation;
  return person;
});
0 голосов
/ 14 декабря 2018

Ответ HTTP-вызова не генерирует объекты класса Person.Ответ на самом деле представляет собой простой объект JavaScript, который явно не имеет метода приветствия () класса Person.

Чтобы это исправить, вы можете применить следующий код:

http.post(...)
    .pipe(map(res => Object.assign(new Person(), res)))
    .subscribe(...);

Функция Object.assign (new Person (), res) скопирует ВСЕ значения res в экземпляр Person.После этой карты у вас будет настоящий экземпляр Person со значениями его свойств, скопированными из ресурса, возвращенного вызовом http.

0 голосов
/ 13 декабря 2018

Вы должны создать так называемый конструктор копирования, который будет принимать все поля объекта:

constructor(firstName: string, lastName: string) {
    this.firstName = firstName;
    this.lastName = lastName;
}

Теперь вы можете сделать

http.post(...)
    .pipe(map(res => new Person(res.firstName, res.lastName)))
    .subscribe(...);

Существует много вариантов этого,конечно.Вы можете просто сделать

constructor(public firstName: string, public lastName: string) {}

, чтобы, например, избежать повторного назначения значений вручную.Или подумайте, как бы вы хотели написать это.Все сводится к тому же: вам нужно создать экземпляр вашего класса, а не использовать тип класса только как тип.

...