Javascript TypeScript中的接口和类

Javascript TypeScript中的接口和类,javascript,typescript,interface,Javascript,Typescript,Interface,在C语言中,接口和类之间存在着巨大的差异。事实上,一个类代表一种引用类型,因此我们可以实际创建基于该类的对象,而接口则是一个类签署的契约,以确保某种行为的存在。特别是,我们不能创建接口的实例 接口的全部要点是公开行为。类通过给出所述行为的一个显式实现来实现它 在这种情况下,尽管接口可能包含属性,但大多数情况下我们关心接口是因为行为问题。所以大多数类型的接口只是行为契约 另一方面,在打字稿上,我似乎有些东西让我感到不安,事实上,我不止一次看到过这一点,这就是这个问题的原因 在一个教程中,我看到:

在C语言中,接口和类之间存在着巨大的差异。事实上,一个类代表一种引用类型,因此我们可以实际创建基于该类的对象,而接口则是一个类签署的契约,以确保某种行为的存在。特别是,我们不能创建接口的实例

接口的全部要点是公开行为。类通过给出所述行为的一个显式实现来实现它

在这种情况下,尽管接口可能包含属性,但大多数情况下我们关心接口是因为行为问题。所以大多数类型的接口只是行为契约

另一方面,在打字稿上,我似乎有些东西让我感到不安,事实上,我不止一次看到过这一点,这就是这个问题的原因

在一个教程中,我看到:

export interface User {
    name: string; // required with minimum 5 chracters
    address?: {
        street?: string; // required
        postcode?: string;
    }
}
但是等一下。为什么
User
是一个界面?如果我们像C#一样思考,
User
不应该是一个界面。事实上,从这个角度看,我们似乎在定义数据类型
User
,而不是行为契约

就像我们在C#中所做的那样,自然的事情是这样的:

export class User {
    public name: string;
    public address: Address;
}
export class Address {
    public street: string;
    public postcode: string;
}
但是,像我们对类那样使用接口来定义数据类型,而不是定义行为契约,这在TypeScript中似乎非常常见


那么TypeScript中的接口是什么?为什么人们在TypeScript中使用接口就像我们在C#中使用CLASE一样?如何在TypeScript中正确使用接口:建立行为契约,或定义属性和对象应有的属性?

考虑在Javascript中,数据通常作为普通对象交换,通常通过JSON:

let data = JSON.parse(someString);
假设这个
数据
用户
对象的数组,我们将把它传递给函数:

data.forEach(user => foo(user))
foo
的键入方式如下:

function foo(user: User) { ... }

但是等等,我们从来没有做过新用户!我们应该吗?我们是否必须编写一个类
User
map
将所有
数据
映射到它,即使结果完全相同,还是要编写一个带有属性的
对象
?不,仅仅为了满足类型系统而这样做是疯狂的,但不会改变运行时的任何内容。一个简单的
接口
描述了特定对象的预期外观(“行为”)就足够了。

仅使用本机反序列化机制,无法反序列化特定类的实例。您只能反序列化为普通的旧javascript对象。此类对象可以附着于typescript接口,但不能是类的实例。如果您需要处理跨越序列化边界的数据,例如预期来自Web服务的数据,请使用接口。如果您需要自己生成这些值的新实例,只需按字面意思构造它们,或者创建一个方便的函数来返回它们,即遵循该接口的对象

一个类本身可以实现一个接口,但是如果您希望同时处理本地构造的类实例和反序列化的、重构的普通对象,那么它可能会变得混乱。您永远无法依赖对象的类基础,因此也无法将其定义为用于该确切目的的类


我已经成功地创建了一个ServerProxy模块,负责从webservice来回发送代码——webservice调用和返回的结果。如果您绑定到淘汰车型或类似车型,您可以使用一个类来封装绑定ui的模型,该类具有一个构造函数,该构造函数知道如何将一个返回的简单旧javascript对象(该对象遵循webservice的仅接口契约)提升到模型类的实例中。

typescript中的接口与C#中的接口类似,因为它们都提供了契约。然而,与只包含方法的C#接口相反,typescript接口还可以描述对象包含的字段或属性。因此,它们也可以用于C#接口无法直接实现的事情

typescript中接口和类之间的一个主要区别是接口没有运行时表示,并且不会为它们发出任何代码。接口的可用性非常广泛。例如,您可以使用对象文字来构造具有接口的对象。比如:

let user: User = {
  name: 'abc',
  address: {
    street: 'xyz',
  },
};
或者,您可以将任何数据对象(例如,通过JSON解析接收的数据)分配给接口(但是您的预检查应该断言它是真正有效的数据)。因此,接口对于数据非常灵活

另一方面,类在运行时有一个与之关联的类型,并且生成了代码。您可以在运行时使用
instanceof
检查类型,并设置了一个原型链。如果将
User
定义为类,则除非调用构造函数,否则它将不是有效的用户。您不能仅仅定义任何类型的合适数据作为
用户
。您需要创建一个新实例并将属性复制到该实例上

我个人的经验法则是:

  • 如果我在处理纯数据(来自不同来源),我会使用接口
  • 如果我在建模具有标识和状态(可能还有修改状态的附加方法)的对象,我将使用一个类

我也是从C#背景来到Typescript的,我也对同样的事情感到好奇。我一直在思考POCO(POTO是一种东西吗?)

那么TypeScript中的接口是什么

似乎说接口是为了“在代码中定义契约”

为什么人们在TypeScript中使用接口就像我们在C#中使用类一样

我同意@deceze的回答

John Papa在他的文章中扩展了类和接口的主题。他建议类最适合“创建多个新实例”
class Car implements ICar {
    foo: string;
    bar(): void {
    }
}

interface ICar {
    foo: string;
    bar(): void;
}
var Car = (function () {
    function Car() {
    }
    Car.prototype.bar = function () {
    };
    return Car;
}());
interface HelloPrinter {
    printHello(): void
}
{
    printHello: () => console.log("hello")
}
const o: HelloPrinter = {
    printHello: () => console.log("hello")
}