Проблема Angular4 HttpClient TypeCheck

Я читал, что новый Angular HttpClient может выполнять проверку типов, на основании чего я пишу следующий код

post(path: string, body: Object = {}): Observable<ValorTest> {
return this.http.post<ValorTest>(path, JSON.stringify(body))
  .map((data: ValorTest) => {
    console.log(typeof data); // Why console displays 'data' as object instead of ValorTest?
    console.log(data instanceof ValorTest); // outputs: false
    console.log(data); // outputs (no type displayed in Chrome's console): {codigo: "INF00001", estado: "Success"}
  })
  .pipe(catchError(this.formatErrors));

}

Я получаю JSON, соответствующий моему классу модели (ValorTest).

Вопрос: почему в console.log тип данных отображается как объект, а не ValorTest?


person Rafael Reyes    schedule 04.03.2018    source источник
comment
Это просто проверка типов, которую вы должны сами позаботиться о приведении к классу ValorTest   -  person yurzui    schedule 04.03.2018
comment
Потому что либо то, что вы прочитали, совершенно неверно, либо вы не совсем поняли это. Все, что делает HttpClient, — это JSON.parse() для преобразования байтов в теле в объект. JSON.parse не знает и не заботится о вашем классе. Он создает POJO, и эти POJO никогда не будут экземплярами какого-либо класса.   -  person JB Nizet    schedule 04.03.2018


Ответы (3)


Если вы просто выполняете проверку типов/утверждение, вы можете использовать instanceof. Если вам действительно нужно напечатать имя класса, вы можете попробовать data.constructor.name:

class TestClass {}

var instance  = new TestClass();

console.log(typeof instance);
// Expected output: "object"

console.log(instance.constructor.name);
// Expected output: "TestClass"

if (instance instanceof TestClass) {
    console.log("instance is TestClass");
}
// Expected output: "instance is TestClass"

Что касается почему: typeof работает только со встроенными типами данных JavaScript, такими как строка, логическое значение, объект и т. д. Если вы посмотрите, как TypeScript транспилируется в JavaScript, и вы поймете, почему во время выполнения JavaScript знает только то, что ваш экземпляр является «объектом».

Обновлено

Это будет работать только с экземплярами, созданными с помощью конструктора new class(). Здесь HttpClient на самом деле не создает для вас экземпляр вашего класса — он просто позволяет вам (в целях разработки) указать с помощью TypeScript тип данных, которые вы ожидаете получить в ответе. Насколько мне известно, HttpClient ничего не делает, чтобы гарантировать (во время выполнения), что данные ответа фактически соответствуют этим ожиданиям. Если вам требуется строгая проверка типов во время выполнения, вам, вероятно, потребуется написать собственную функцию защиты типов.

Итак, если у вас есть такой класс:

class TestClass {
    prop: string;
    constructor() { }
    method(): void {}
}

Вы можете написать защиту типа следующим образом:

function isTestClass(obj: TestClass | object): obj is TestClass {
    // add whatever type checking logic you need here
    return (<TestClass>obj).method !== undefined && 
           (<TestClass>obj).prop !== undefined; 
}

И проверьте свои данные во время выполнения:

var obj_a = { prop: "" },
    obj_b = { prop: "", method: null };

console.log(isTestClass(obj_a));
// Expected output: false

console.log(isTestClass(obj_b));
// Expected output: true

Я мог бы сделать функцию защиты типа статическим методом моего класса.

Кроме того, вы можете рассмотреть возможность использования интерфейса для ваших данных ответа вместо класса - в основном потому, что это может помочь интуитивно понять, что данные, которые вы получили, могут иметь или не иметь реализацию, которую вы ожидаете.

Дополнительные сведения о защите типов, определяемых пользователем, см. на странице https://www.typescriptlang.org/docs/handbook/advanced-types.html

person Chris Yeager    schedule 04.03.2018
comment
Привет, использование instanceof возвращает fase. JSON, который я читаю, соответствует структуре модели - person Rafael Reyes; 04.03.2018
comment
@RafaelReyes Я обновил свой ответ после прочтения вашего ответа. Помогает ли это немного объяснить ситуацию? - person Chris Yeager; 04.03.2018

Вызов typeof будет выдавать только встроенные типы JS, что вы, вероятно, захотите сделать, это проверить instanceof, который сообщит вам, соответствует ли возвращаемое значение вашему пользовательскому типу!

person OClyde    schedule 04.03.2018
comment
Быстрое дополнение: важно помнить, что TypeScript является структурным, а не номинальным, а это означает, что даже объект, соответствующий структуре вашего пользовательского типа, в этом случае будет выдавать true. Если вы хотите проверить фактический тип вашей переменной, просто зарегистрируйте ее без typeof или instanceof, консоль Chrome сообщит вам тип! - person OClyde; 04.03.2018
comment
Привет, я уже отредактировал вопрос на основе ваших комментариев. Использование instanceof возвращает false, и при регистрации одного объекта (данных) консоль Chrome не отображает тип, а отображает структуру данных. - person Rafael Reyes; 04.03.2018

не связанный с HttpClient, все коды и типы typescript преобразуются в javascript, который может скомпилировать браузер, затем javascript обрабатывает их с использованием объектов, поэтому в консоли он просто знает объекты.

person Fateme Fazli    schedule 04.03.2018