HttpClient类型安全似乎忽略了接口

时间:2017-10-19 21:31:20

标签: angular typescript

TL; DR:

  1. 定义了一个角度界面并绑定到HttpClient.get()个响应。
  2. 响应已映射到看似通用的object类型。
  3. 未在idtitle等界面上定义的属性可以在响应中访问,也可以从.html调用(例如。<p>Title is: {{message?.title}}</p>
  4. 如果某个界面是合同,那么它不应该阻止其中一些吗?
  5. 来自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时,仍然创建了数据对象:

    enter image description here

    数据是包含字段idtitle的通用对象。致data.foo的回复undefined

    此外,虽然界面阻止我直接访问这些 id 标题字段,但它们仍然可以通过data['id']之类的调用获得。它们也可以在HTML中引用。

    <h1>
      id: {{message.id}}
      <br>
      title: {{message?.title}}
    </h1>
    

    这会被渲染!事实上,界面似乎唯一阻止我做的事情是:

    `this.message.title`
    

    我觉得这很酷......但是如果这些字段可以通过this.message['title']访问或者在html文件中引用,那么界面的重点是什么?

    enter image description here

1 个答案:

答案 0 :(得分:0)

从Java后台来时,TypeScript类型化的普遍问题是类型不被强制执行。每当您在TypeScript中进行转换时,如果对象不是该类的对象,则不会引发运行时异常。稍后在访问该对象的缺失字段时会引发异常。

您要做的不是编译时间类型检查(就像TypeScript一样),而是要强制执行特定类型的响应。

您可以通过手动检查响应来完成此操作:

    http.get<FooInterface>('/api/items').subscribe(data => {
        if (typeof data !== 'object')
          throw new Error('Expected an object')
        if (typeof data.foo !== 'string')
          throw new Error('Expected a string property')
        this.message = data;
    });

如果要自动执行此操作,请查看JSON模式验证。除了TypeScript类之外,您还需要定义JSON模式。 a library可以帮助您保持同步。还有一些库可以自动从中生成它们Spring REST端点,因此您可以使其与后端服务保持同步。