我已经读过新的Angular的HttpClient可以执行TypeChecking,基于我写下面的代码
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?
如果你只是做类型检查/断言,你可以使用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的内置数据类型,例如string,boolean,object等。如果你look at the way TypeScript transpiles到JavaScript,你可以理解为什么在运行时JavaScript只知道你的实例是一个“对象” 。
更新
这仅适用于使用新的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
typeof
调用只会发出JS的内置类型,您可能要做的是检查instanceof
,它会告诉您返回的值是否与您的自定义类型匹配!
与HttpClient无关,所有的打字稿代码和类型转换为浏览器可以编译的javascript,然后javascript使用对象处理它们,所以在控制台中它只知道对象。