'interface' 和 'declare interface' 的区别

48

这两者之间有什么区别(如果有的话):

declare interface SomeInterface {
    //members here
}

并且:

interface SomeInterface {
    //members here
}

?


2
大家好--我已经整理了一些评论。请不要将标签编辑到问题的标题中,也不要反复进行相同的建议性编辑。 - josliber
@josliber,建议的编辑是因为当我创建问题时找不到这个问题。这个问题在问题中没有提到TypeScript的参考。该问题已从OP原始发布中进行了编辑,以删除typescript一词。再次强调,TypeScript这个词是“有机的对话语气”,它很容易阅读,您不同意吗? - Christian Matthew
2
@ChristianMatthew 这个问题已经标记了TypeScript,这应该足够了。如果您想进一步讨论此事,我建议您在meta.stackoverflow.com上发布,而不是在这里进行编辑战。 - josliber
2个回答

37

declare关键字通常用于类型定义中,用来描述在JavaScript代码中已经存在的类或变量。

declare interfaceinterface没有区别,因为:

  • 接口没有代码生成,它们只存在于Typescript代码中,所以你不能declare interface 定义在JavaScript代码中的接口;
  • Typescript中的接口本质上是一个声明,它没有方法体、属性值等内容,因此declare interfaceinterface在语法上是相等的。

19
“declare interface” 和 “interface” 在语法上显然是不同的(一个由两个单词组成,另一个只有一个单词),但在语义上是相等的。 - Mike Lischke
1
这是不正确的。在最终的JS文件中,声明的接口值不会被缩小/重命名,而常规接口将被删除。此外,如果未声明接口内部的属性可以被缩小/重命名。 - Luke
1
@Luke,你所描述的是明显错误的(在TS Playground上试一下:TypeScript中所有接口类型都会经历类型擦除,不仅包括interface还包括declare interface。你有关于“声明的接口不会被缩小”的来源或引用吗?你是想到了出现在.d.ts输出文件中的declare interface(而不是.js输出文件)吗?如果是这样,那么你会发现.d.ts文件中既有declare interface类型也有interface类型。未使用类型的删除根本不是由TypeScript完成的,而是由其他地方完成的。 - Dai

3

为了回答这个问题,要理解的一个概念是接口声明合并。在TypeScript中,接口声明合并的工作原理如下:

每当我们多次声明一个接口(带或不带declare关键字),它们将被合并在一起。这意味着接口现在具有合并在一起的两个接口的属性。最好通过以下示例来理解:

// Usually this interface would be defined in another file
// or package already
interface foo { num1: number }

// Because the interface foo is already defined TS will apply 
// interface declaration merging
declare interface foo{num2: number}
// Declare keyword makes it more explicit that is was defined
// somewhere else, it adds n


let fooObj: foo = { num1: 1 }
// Typescript will give the following error:
// Property 'num2' is missing in type '{ num1: number; }' 
// but required in type 'foo'.(2741)

// It requires the property num2 because after the interface merging 
// the interface contains both num1: number, and num2: number properties


// This interface declaration merging functionally similar to 
// the foo interface above, just without the declare keyword
interface bar{ string1: string }
interface bar{ string2: string }

let barObj: bar = { string1: 'hi', string2: 'hithere' }

declare关键字在接口之前的作用

请注意,declare interface只是更明确地说明该接口在其他地方定义(比如其他文件、包等) ,没有添加任何额外的功能。

同时还要注意,接口仅仅是为了给TS编译器提供附加类型信息,在编译后的JS中并不存在。上面的代码编译后会变成以下的JS:

"use strict";
let fooObj = { num1: 1 };
let barObj = { string1: 'hi', string2: 'hithere' };

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接