简体   繁体   English

TypeScript中“声明类”和“接口”有什么区别

[英]What's the difference between "declare class" and "interface" in TypeScript

In TypeScript, when creating.d.ts source declaration files, which is preferable and why?在 TypeScript 中,当创建 .d.ts 源声明文件时,哪个更好,为什么?

declare class Example {
    public Method(): void; 
}

or或者

interface Example {
    Method(): void;
}

The differences that I can tell are that interfaces can't have static methods, so you must use a class for that.我可以说的区别是接口不能有 static 方法,所以你必须为此使用 class。 Both don't product any JS output, so perhaps it doesn't matter?两者都不产生任何 JS output,所以也许没关系?

interface is for when you simply want to describe the shape of an object. interface适用于您只想描述对象的形状。 There's no code generation, ever, for interfaces -- they're solely an artifact in the type system. 对接口来说,没有代码生成 - 它们只是类型系统中的工件。 You'll see no difference in the code generation for a class depending on whether or not it has an implements clause. 您将看到类的代码生成没有区别,具体取决于它是否具有implements子句。

declare class is for when you want to describe an existing class (usually a TypeScript class, but not always) that is going to be externally present (for example, you have two .ts files that compile to two .js files and both are included via script tags in a webpage). declare class用于描述当前要在外部存在的现有类(通常是TypeScript类,但并非总是如此)(例如,您有两个.ts文件,它们编译为两个.js文件,并且都包含在内通过网页中的script标签)。 If you inherit from a class using extends (regardless of whether the base type was a declare class or a regular class ) the compiler is going to generate all the code to hook up the prototype chain and forwarding constructors and what not. 如果从使用extends继承class (无论基类型是declare class还是常规class ),编译器将生成所有代码以连接原型链和转发构造函数,而不是。

If you try to inherit from a declare class that should have been an interface, you are going to have a runtime error because that generated code will be referring to an object with no runtime manifestation. 如果您尝试从应该是接口的declare class继承,那么您将遇到运行时错误,因为生成的代码将引用没有运行时表现形式的对象。

Conversely, if you simply implement an interface that should have been a declare class , you're going to have to re-implement all the members yourself and won't be taking advantage of any code re-use from the would-be base class, and functions that check the prototype chain at runtime will reject your object as not actually being an instance of the base class. 相反,如果您只是implement一个应该是declare class的接口,那么您将不得不自己重新实现所有成员,并且不会利用可能基类中的任何代码重用。 ,以及在运行时检查原型链的函数将拒绝您的对象,因为它实际上不是基类的实例。

To get really nerdy, if you have a C++ background, you can roughly think of interface as typedef and declare class as an extern declaration of a constructor that strictly lacks a definition in this compile unit. 为了得到真正的书呆子,如果你有C ++背景,你可以粗略地将interface视为typedef并将declare class声明为构造函数的extern声明,该构造函数严格缺少此编译单元中的定义。

From a pure consumption side (writing imperative code, not adding new types), the only difference between interface and declare class is that you can't new an interface. 从纯粹的消费方面(编写命令式代码,而不是添加新类型), interfacedeclare class之间的唯一区别是你不能new一个接口。 However, if you intend to extend / implement one of these types in a new class , you absolutely have to have chosen correctly between interface and declare class . 但是,如果您打算在新class extend / implement其中一种类型,则必须在interfacedeclare class之间正确选择。 Only one of them will work. 只有其中一个可以工作。

Two rules that will serve you well: 两条规则将很好地为您服务:

  • Is the name of the type aligning with a constructor function (something invokable with new ) that's actually present at runtime (eg Date is, but JQueryStatic is not)? 类型的名称是否与运行时实际存在的构造函数(可用new调用的东西)对齐(例如Date是,但JQueryStatic不是)? If no , you definitely want interface 如果不是 ,你肯定想要interface
  • Am I dealing with a compiled class from another TypeScript file, or something sufficiently similar? 我是在处理来自另一个TypeScript文件的编译类,还是类似的东西? If yes , use declare class 如果 ,请使用declare class

You can implement the interface: 您可以实现界面:

class MyClass implements Example {
    Method() {

    }
}

Whereas the declare class syntax is really intended to be used to add type definitions for external code that isn't written in TypeScript - so the implementation is "elsewhere". declare class语法实际上是用于为不是用TypeScript编写的外部代码添加类型定义 - 因此实现是“其他地方”。

In layman's terms, declare is used in .ts / d.ts files to tell the compiler that we should expect the keyword we're declaring to exist in that environment, even if it is not defined in the present file. 在外行人的术语中, declare.ts / d.ts文件中用于告诉编译器我们应该期望我们declaring在该环境中存在的关键字,即使它没有在当前文件中定义。 This will then allow us to have type safety when using the declared object, as the Typescript compiler now knows that some other component may provide that variable. 这将允许我们在使用声明的对象时具有类型安全性,因为Typescript编译器现在知道某些其他组件可以提供该变量。

Difference between declare and interface in TS: TS中declareinterface区别:

declare: 宣布:

declare class Example {
    public Method(): void; 
}

In the above code declare lets the TS compiler know that somewhere the class Example is declared. 在上面的代码declare让TS编译器知道某个类的Example被声明了。 This does not mean that the class is magically included. 这并不意味着该课程被神奇地包括在内。 You as a programmer are responsible for having the class available when you are declaring it (with the declare keyword). 作为程序员,您负责在声明它时使用该类(使用declare关键字)。

interface: 接口:

interface Example {
    Method(): void;
}

An interface is a virtual construct that only exists within typescript. interface是仅存在于打字稿中的虚拟构造。 The typescript compiler uses it for the sole purpose of type checking. typescript编译器仅将其用于类型检查。 When the code is compiled to javascript this whole construct will be stripped out. 当代码编译为javascript时,整个构造将被剥离。 The typescript compiler uses interfaces in order to check if objects have the right structure. typescript编译器使用接口来检查对象是否具有正确的结构。

For example when we have the following interface: 例如,当我们有以下界面时:

interface test {
  foo: number,
  bar: string,
}

The objects which we define which have this interface type need to match the interface exactly: 我们定义的具有此接口类型的对象需要与接口完全匹配:

// perfect match has all the properties with the right types, TS compiler will not complain.
  const obj1: test = {   
    foo: 5,
    bar: 'hey',
  }

it just feels redundant!?只是觉得多余!?

I understand that I need a d.ts (declaration) file to make use of types outside of the project, but why not use the same declaration instead of an additional interface/type?我知道我需要一个 d.ts(声明)文件来使用项目之外的类型,但为什么不使用相同的声明而不是额外的接口/类型?

Then type and interface seems to be the same as well!?那么类型和界面似乎也一样!?

I've checked the typescript code (GitHub) and they use (it seems) type for one-ligner types and interfaces for objects with more properties...我已经检查了打字稿代码(GitHub),他们使用(似乎)类型来表示单一类型的类型和具有更多属性的对象的接口......

=> to me personally it feels like interfaces belong to classes and types to everything else, but that's just an assumption far from the origin topic ^^ => 就我个人而言,感觉接口属于类,类型属于其他一切,但这只是远离原始主题的假设 ^^

any enlightening is welcome, appreciating.欢迎任何启发,欣赏。

PS: do I only need a declaration file when my code is written in JS (to make it understood in typescript projects where I import the package?) I mean otherwise I could export types easily. PS:当我的代码是用 JS 编写时,我是否只需要一个声明文件(以便在我导入包的打字稿项目中理解它?)我的意思是否则我可以轻松导出类型。 maybe I get closer...?也许我更接近...?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 Typescript 中使用 `: Interface` 和 `as Interface` 有什么区别? - What's the difference between using `: Interface` and `as Interface` in Typescript? 在打字稿定义中声明 var 和声明 const 有什么区别? - What is the difference between declare var and declare const in typescript definitions? TypeScript中的JQuery和JQueryStatic接口有什么区别? - What is the difference between the JQuery and the JQueryStatic interface in TypeScript? 在Typescript中,类型和接口有什么区别? - In Typescript, what is the difference between type and interface? TypeScript:模块和具有静态成员的类之间有什么区别? - TypeScript: What's the difference between a Module and a Class with Static members? TypeScript声明合并中的导出接口和导出默认接口之间有什么区别? - What's the difference between export interface and export default interface in typescript declaration merging? 为非Typescript类声明Typescript接口 - Declare Typescript Interface for non Typescript class 打字稿中的String []和[String]有什么区别? - What's the difference between String[] and [String] in typescript ? Javascript/Typescript:导出单个函数或 const 类有什么区别? - Javascript/Typescript: what's the difference between exporting single functions or a const class? javascript:函数和类有什么区别 - javascript: what's the difference between a function and a class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM