【发布时间】:2018-04-01 00:59:59
【问题描述】:
TL;DR:
- 定义了一个角度接口并将其绑定到
HttpClient.get()响应。 - 响应被映射到看似通用的
object类型。 - 诸如
id和title之类的接口上未定义的属性可以在响应中访问,也可以从调用的.html 中访问(例如<p>Title is: {{message?.title}}</p>。 - 如果接口是合同,它不应该阻止其中的一些吗?
来自 Java 背景的 Angular 4 新手,在 HttpClient 类型安全方面遇到了挫折。正如this guide 指出的那样,可以将一个接口传递给http.get<> 以对HTTP 响应进行类型检查。
考虑一个带有单个 foo 字段的基本接口:
export interface FooInterface{
foo: string;
}
按照上述指南,这个接口可以很容易地绑定到响应:
export class RestComponent {
message: FooInterface;
http.get<FooInterface>('/api/items').subscribe(data => {
this.message = data;
console.log(this.message);
console.log(typeof(this.message));
console.log(this.message.foo);
});
此时,我点击了一个没有 foo 字段的随机 API。实际的 API 有两个字段:id 和 title。令我惊讶的是,当我点击这个 API 时,仍然创建了数据对象:
Data 是具有字段id 和title 的通用对象。对data.foo 的调用返回undefined。
此外,虽然界面阻止我直接访问这些 id 和 title 字段,但它们仍然可以通过像 data['id'] 这样的调用来使用。它们也可以在 HTML 中引用。
<h1>
id: {{message.id}}
<br>
title: {{message?.title}}
</h1>
这会被渲染!事实上,界面似乎唯一能做的就是阻止我做类似的事情:
`this.message.title`
我想这很酷……但如果这些字段可以通过this.message['title'] 访问或在 html 文件中引用,那么界面的意义何在?
【问题讨论】:
-
仅仅提供一个泛型类型并不不意味着 Angular 会进行任何类型转换或验证。 "Typechecking" 可能不是文档引用此内容的最清晰方式。这只是对您有益的提示,因此您可以记录您期望收到的形状,并在随后与之交互时从编译器获得帮助。如果您需要一些转换,则必须自己编写。
-
这就是我的感觉,但我认为界面是一种契约,而不是一种暗示。您是否推荐任何实用程序/快捷方式来进行这些转换?
-
我不确定你从哪里得到这个想法,请注意 TS 的类型是 only 在编译时。我们只是根据需要编写了自己的映射方法;如果你想要一个图书馆,我建议你去 NPM。
-
我想我认为我与 java 的对应关系太多了,谢谢你的澄清
-
具有 C# 或 Java 背景的开发人员经常遇到 TS 类型的问题,这是有原因的。此外,
data['id']是一种在需要时跳过类型检查的合法技术,并且由于明显的原因无法使用 JIT 编译器检查模板中的类型,因为它是一个被 TS 忽略的字符串——但它们肯定会被 AOT 检查.
标签: angular typescript