何时在TypeScript / Angular2中使用Interface和Model

时间:2016-06-06 08:30:14

标签: angular typescript

我最近使用TypeScript观看了Angular 2的教程,但不确定何时使用接口以及何时使用模型来保存数据结构。

界面示例:

export interface IProduct {
    ProductNumber: number;
    ProductName: string;
    ProductDescription: string;
}

模型示例:

export class Product {
    constructor(
        public ProductNumber: number,
        public ProductName: string,
        public ProductDescription: string
    ){}
}

我想从URL加载JSON数据并绑定到接口/模型。有时我想要一个数据对象,其他时候我想要保持对象的数组。

我应该使用哪一个?为什么?

5 个答案:

答案 0 :(得分:107)

接口仅在编译时。这样只允许您检查收到的预期数据是否遵循特定结构。为此,您可以将内容转换为此界面:

this.http.get('...')
    .map(res => <Product[]>res.json());

请参阅以下问题:

您可以使用类进行类似的操作,但与类的主要区别在于它们存在于运行时(构造函数),您可以使用处理来定义它们中的方法。但是,在这种情况下,您需要实例化对象才能使用它们:

this.http.get('...')
    .map(res => {
      var data = res.json();
      return data.map(d => {
        return new Product(d.productNumber,
          d.productName, d.productDescription);
      });
    });

答案 1 :(得分:36)

接口描述了的合同或新的类型。 它是纯粹的Typescript元素,因此它不会影响Javascript。

模型,即,是一个实际的JS函数,用于生成新对象。

  

我想从URL加载JSON数据并绑定到接口/模型。

寻找模型,否则它仍然是Javascript中的JSON。

答案 2 :(得分:5)

我个人为我的模型使用接口,关于这个问题有 3 所学校,最常根据您的要求选择一所:

1- 接口:

interface 是一个虚拟结构,它只存在在 TypeScript 的上下文中。 TypeScript 编译器仅将接口用于类型检查目的。一旦您的代码被转译为它的目标语言,它就会从它的界面中剥离出来——JavaScript 不是类型化的。

interface User {
 id: number;
 username: string;
}
// inheritance
interface UserDetails extends User {
 birthdate: Date;
 biography?: string;  // use the '?' annotation to mark this property as optionnal
}

如果您使用的是来自 interfaceHttpClient,如果您使用的是 Angular 4.3.x 及更高版本,则将服务器响应映射到 HttpClientModule 是直接的。

getUsers() :Observable<User[]> {
 return this.http.get<User[]>(url); // no need for '.map((res: Response) => res.json())' 
}

何时使用接口:

  • 您只需要定义服务器数据,而不会为最终输出引入额外的开销。
  • 您只需要传输数据,无需任何行为或逻辑(构造函数初始化、方法)
  • 你不经常从你的界面实例化/创建对象
    • 使用简单的对象字面量表示法let instance: FooInterface = { ... };,您可能会冒着到处都是半实例的风险。
    • 这不会强制执行类给出的约束(构造函数或初始化逻辑、验证、私有字段的封装......等)
  • 您需要为您的系统定义合同/配置(全局配置)

2- 类:

A class 定义对象的蓝图。它们表达了这些对象将继承的逻辑、方法和属性。

class User {
 id: number;
 username: string;
 constructor(id :number, username: string)  {
  this.id = id;
  this.username = username.replace(/^\s+|\s+$/g, ''); // trim whitespaces and new lines
 }
}
// inheritance
class UserDetails extends User {
 birthdate: Date;
 biography?: string;  
 constructor(id :number, username: string, birthdate:Date, biography? :string )  {
   super(id,username);
  this.birthdate = ...;
 }
}

何时使用类:

  • 您实例化您的类并随着时间的推移更改实例状态。
  • 类的实例需要查询或改变其状态的方法
  • 当您想将行为与数据更紧密地联系起来时;
  • 您对实例的创建实施限制。
  • 如果你只在你的类中写了一堆属性赋值,你可以考虑使用类型来代替。

2- 类型:

随着最新版本的打字稿,接口和类型变得越来越相似。 types 不在您的应用程序中表达逻辑或状态。当您想描述某种形式的信息时,最好使用类型。它们可以描述不同形状的数据,包括字符串、数组和对象等简单结构。 与接口一样,类型只是虚拟结构,不会转换为任何 javascript,它们只是帮助编译器让我们的生活更轻松。

type User = {
 id: number;
 username: string;
}
// inheritance
type UserDetails = User & {
  birthDate :Date;
  biography?:string;
}

何时使用类型:

  • 将其作为简洁的函数参数传递
  • 描述一个类构造函数的参数
  • 记录从 API 传入或传出的中小型对象。
  • 它们不携带状态或行为

答案 3 :(得分:0)

为了让你的代码灵活,我们需要使用接口。 创建接口并在类的构造函数中传递接口类型。这使用了依赖注入。

优点:

  1. 如果接口的参数有变化,不需要改变类。 2.为了测试,您可以在类的构造函数中使用模拟数据。

答案 4 :(得分:-12)

使用Class而不是Interface ,这是我在所有研究后发现的。

为什么呢?单独一个类的代码少于类加接口。 (无论如何,你可能需要一个数据模型类)

为什么呢?类可以充当接口(使用implements而不是extends)。

为什么呢?接口类可以是Angular依赖注入中的提供者查找标记。

from Angular Style Guide

基本上,一个类可以做所有,接口将做什么。 所以可能永远不需要使用界面