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

I_L*_*FOO 177 typescript angular

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

界面示例:

export interface IProduct {
    ProductNumber: number;
    ProductName: string;
    ProductDescription: string;
}
Run Code Online (Sandbox Code Playgroud)

型号示例:

export class Product {
    constructor(
        public ProductNumber: number,
        public ProductName: string,
        public ProductDescription: string
    ){}
}
Run Code Online (Sandbox Code Playgroud)

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

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

Thi*_*ier 125

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

this.http.get('...')
    .map(res => <Product[]>res.json());
Run Code Online (Sandbox Code Playgroud)

看到这些问题:

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

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

  • 谢谢你的详细解答.如果接口仅在编译时使用,编译器如何在不实际检查http get的情况下检查JSON文件的结构?如果它不能,那么甚至打扰界面有什么意义呢? (25认同)
  • @Sampath也许Angular样式指南已经更新,因为我现在看到这个"考虑使用数据模型的接口.".对于数据模型,Implies更喜欢接口而不是类. (8认同)
  • @I_LIKE_FOO编译器不需要检查get调用.它只关心检查它知道的类型以及它们是否正确对齐.`var data = res.json();`实际上是'var data:any = res.json();`到编译器,所以我们丢失了对`data`的所有类型检查.这里更有用的是`var data:ProductDto [] = res.json();```ProductDto`是一个接口,用于对返回的json中的数据结构进行建模. (6认同)
  • 是的,但问题是他们不是设计打字稿的大师神.那将是微软和公司.他们倾向于在适当的时候支持接口和类.还有奖励点......一个是运行时,另一个是编译时 (4认同)
  • 更多:`Angular样式指南说不使用接口.总是使用类.请参阅https://angular.io/guide/styleguide#style-03-03 (3认同)
  • 我遇到的一件事,似乎值得在这里分享:-接口只是编译时实体,已从dists的运行时包中删除,而类仍在运行时dists中保留。我们的类正在被转换为与ES5兼容的函数形式,现在已成为我们最终JavaScript应用程序中不必要的部分。如果我们有一个大型应用程序,并重复使用类作为模型类型注释的这种模式,那么最终可能会给用户的捆绑软件增加很多额外的负担。 (2认同)

pie*_*909 39

接口描述了无论是对一个合同或新类型.它是一个纯粹的Typescript元素,因此它不会影响Javascript.

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

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

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


Ben*_*har 12

I personally use interfaces for my models, There hoewver are 3 schools regarding this question, and choosing one is most often based on your requirements:

1- Interfaces:

interface is a virtual structure that only exists within the context of TypeScript. The TypeScript compiler uses interfaces solely for type-checking purposes. Once your code is transpiled to its target language, it will be stripped from its interfaces - JavaScript isn’t typed.

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

Mapping server response to an interface is straight forward if you are using HttpClient from HttpClientModule if you are using Angular 4.3.x and above.

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

when to use interfaces:

  • You only need the definition for the server data without introducing additional overhead for the final output.
  • You only need to transmit data without any behaviors or logic (constructor initialization, methods)
  • You do not instantiate/create objects from your interface very often
    • Using simple object-literal notationlet instance: FooInterface = { ... };, you risk having semi-instances all over the place.
    • That doesn't enforce the constraints given by a class ( constructor or initialization logic, validation, encapsulation of private fields...Etc)
  • You need to define contracts/configurations for your systems (global configurations)

2- Classes:

A class defines the blueprints of an object. They express the logic, methods, and properties these objects will inherit.

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 = ...;
 }
}
Run Code Online (Sandbox Code Playgroud)

when to use classes:

  • You instantiate your class and change the instances state over time.
  • Instances of your class will need methods to query or mutate its state
  • When you want to associate behaviors with data more closely;
  • You enforce constraints on the creation of your instaces.
  • If you only write a bunch of properties assignments in your class, you might consider using a type instead.

2- Types:

With the latest versions of typescript, interfaces and types becoming more similar. types do not express logic or state inside your application. It is best to use types when you want to describe some form of information. They can describe varying shapes of data, ranging from simple constructs like strings, arrays, and objects. Like interfaces, types are only virtual structures that don't transpile to any javascript, they just help the compiler making our life easier.

type User = {
 id: number;
 username: string;
}
// inheritance
type UserDetails = User & {
  birthDate :Date;
  biography?:string;
}
Run Code Online (Sandbox Code Playgroud)

when to use types:

  • pass it around as concise function parameters
  • describe a class constructor parameters
  • document small or medium objects coming in or out from an API.
  • they don't carry state nor behavior


M_F*_*and 5

正如 @ThierryTemplier 所说,从服务器接收数据并在组件之间传输模型(以保留智能感知列表并产生设计时错误),使用接口很好,但我认为将数据发送到服务器(DTO)最好使用类来获取从模型自动映射 DTO 的优点。