在TypeScript中的Type与Interface的区别

Type vs. Interface 是TypeScript中最令人困惑和有趣的事情之一。我们将尝试解开这种困惑。

TypeScript是建立在JavaScript之上的,它增加了静态类型。拥有类型对开发人员来说是一件很好的事情。编写类型可能很困难,但从长远来看你不会后悔。

TypeScript具有所有基本类型,如number、string、boolean等等。除了基本类型之外,TypeScript允许我们创建自定义类型,并通过类型别名和接口来定义对象的外观, 分别。

类型别名只是一种类型。使用自定义名称(别名)创建一个类型就是类型别名,仅此而已。

让我们看看接口类型别名的基本语法。

基本语法

接口

接口将使用interface关键字声明。请检查下面的接口语法。

interface InterfaceName {
    keyName: typeOfKey
    ...
}

看看下面的示例。

interface Site {
    name: string;
    url: string;
    pagesCount: number;
}

const yaoweibin: Site = {
    name: 'Geekflare',
    url: 'https://yaoweibin.cn/',
    pagesCount: 25
}

类型别名

类型别名将使用type关键字声明。请检查下面的类型别名语法。

type TypeName = {
    keyName: typeOfKey;
    ...
}

看看下面的示例。

type Site = {
    name: string;
    url: string;
    pagesCount: number
}

const yaoweibin: Site = {
    name: 'Geekflare',
    url: 'https://yaoweibin.cn/',
    pagesCount: 25
}

我们使用接口类型别名Site创建了一个类型。两者都是有效的,并且可以用于上面示例中提到的对象类型。只是上面示例中的语法不同,这是显而易见的。

让我们继续探索它们之间的区别,以找到更多的东西。

元组

TypeScript中的元组是一个有预定义长度的数组。它定义了每个索引的类型。

我们可以使用类型别名来声明元组。但我们不能使用接口来做到这一点。让我们看看如何使用类型别名。

type Site = [string, string, number]

const yaoweibin: Site = ['Geekflare', 'https://yaoweibin.cn/', 25]

在上面的示例中,我们为数组的每个索引元素定义了类型。如果我们在数组中给出其他类型,TypeScript会抛出一个错误。

我们不能用接口做到这一点吗?

我们不能像使用类型别名那样完全做到这一点。接口用于对象类型。所以,我们需要在对象内部使用元组才能在接口中使用它。让我们看一个例子。

interface Site {
    details: [string, string];
    pagesCount: number;
}

const yaoweibin: Site = {
    details: ['Geekflare', 'https://yaoweibin.cn/'],
    pagesCount: 25,
}

如果你看一下代码,我们在接口中有一个名为details的元组。因此,我们可以在接口中使用元组。

类似地,我们可以对单个类型(例如string、number、boolean等)使用类型别名。由于接口用于对象类型,我们可以将其用于单个类型,如类型别名。

另一个有趣的事情是,我们可以在接口中使用类型别名元组。请检查下面的示例。

类型细节= [string, string]

接口站点{
details:细节;
pagesCount:数字;
}

const yaoweibin:Site = {
details:[‘Geekflare','https://yaoweibin.com/'],
pagesCount:25,
}

让我们继续下一件事。

声明合并-接口

声明合并是使用TypeScript将具有相同名称的接口类型合并在一起的方法。让我们看一个例子,以便更清楚地理解。

 接口网站{
     名称:字符串;
}
 
接口网站{
     url:字符串;
}
 
接口网站{
     pagesCount:数字;
}
 
const极客网:网站= {
     名称:'Geeflare',
     url:'https://yaoweibin.com/',
     pagesCount:25,
}  

如果您看到上面的代码,我们已经声明了具有相同名称的接口3次。 TypeScript编译器将所有这3个表单编译为单个对象类型,其中包括具有相同名称的接口中的所有类型。

您可以通过从 yaoweibin 对象中删除一个键来确认声明合并。如果从 yaoweibin 中删除键之一,您将看到错误。

我们无法使用类型别名执行相同的操作。大多数人不使用该功能。一般而言,具有相同名称的多个接口会令人困惑。

类型别名粉丝,不要担心接口的此功能😅。

扩展

假设您声明了一个类型。现在,您想要声明另一种类型,并包括先前类型的类型。在这种情况下,我们可以扩展先前的类型。我们可以使用接口类型别名来做到这一点。

让我们看看它们。

界面

在TypeScript中有一个名为 extends 的关键字可用于此用例。我们将使用它来扩展接口。让我们来看看例子。

 接口网站{
     名称:字符串;
     url:字符串;
     pagesCount:数字;
}
 
接口Geekflare扩展网站{
     创始人:字符串;
}
 
const极客网:Geekflare = {
     名称:'Geekflare',
     url:'http://yaoweibin.cn/',
     pagesCount:25,
     创始人:'Chandan'
}  

我们通过扩展 Site 接口创建了 Geekflare 接口。所有 Site 的类型都将出现在 Geeflare 接口中,并包括它们自己的类型。您可以删除 yaoweibin 变量中的 name 键以确认。

我们可以扩展多个接口,如下所示。

 接口FirstHalf {
     名称:字符串;
}
 
接口SecondHalf {
     年龄:数字
}
 
接口人扩展FirstHalf,SecondHalf {
     职业:字符串
}
 
const人:人= {
     名称:'Geekflare',
     年龄:7,
     职业:'帮助技术人员'
}  

尝试扩展超过2个接口以获得乐趣。我们还可以扩展类型别名与接口。

 类型网站= {
     名称:字符串;
     url:字符串;
     pagesCount:数字;
}
 
接口Geekflare扩展Site {
     创始人:字符串;
}
 
const极客网:Geekflare = {
     名称:'Geekflare',
     url:'http://yaoweibin.cn/',
     pagesCount:25,
     创始人:'Chandan'
}  

在上面的示例中,我们仅扩展了一个类型。您可以像上一个示例中扩展一样多次扩展。

让我们看看如何使用类型别名进行操作。

类型别名

我们可以使用TypeScript中的交集类型扩展类型别名。让我们看一个例子。

type Site = {
    name: string;
    url: string;
    pagesCount: number;
}

type Geekflare = Site & {
    founder: string;
}

const yaoweibin: Geekflare = {
    name: 'Geekflare',
    url: 'http://yaoweibin.cn/',
    pagesCount: 25,
    founder: 'Chandan'
}

我们使用交集(&)Site类型扩展为Geekflare类型,并为其添加了founder属性。您可以通过从yaoweibin变量中删除一个键来测试它,这将导致错误。

与接口类似,我们可以按以下方式扩展多个类型。

type FirstHalf = {
    name: string;
}

type SecondHalf = {
    age: number
}

type Person = FirstHalf & SecondHalf & {
    profession: string
}

const person: Person = {
    name: 'Geekflare',
    age: 7,
    profession: 'Helping Techies'
} 

我们还可以像接口扩展类型别名一样扩展接口。请查看下面的示例。

interface Site {
    name: string;
    url: string;
    pagesCount: number;
}

type Geekflare = Site & {
    founder: string;
}

const yaoweibin: Geekflare = {
    name: 'Geekflare',
    url: 'http://yaoweibin.cn/',
    pagesCount: 25,
    founder: 'Chandan'
}

尝试扩展类型别名和接口的组合。

实现

这不是接口和类型别名之间的区别,只是了解class的一个特性。

一个类可以以相同的方式实现接口和类型别名。让我们分别看一下它们的示例。

接口

interface Site {
    name: string;
    url: string;
    pagesCount: number;
}

class Geekflare implements Site {
    name = 'Geekflare'
    url = 'http://yaoweibin.cn/'
    pagesCount = 25

    constructor() {
        console.log(this.name, this.url, this.pagesCount)
    }
}

类型别名

type Site = {
    name: string;
    url: string;
    pagesCount: number;
}

class Geekflare implements Site {
    name = 'Geekflare'
    url = 'http://yaoweibin.cn/'
    pagesCount = 25

    constructor() {
        console.log(this.name, this.url, this.pagesCount)
    }
}

注意:需要记住的一件事是,我们不能使用类实现联合(|)交集(&)类型。

最后的话

正如你在文章中所看到的,我们可以使用类型别名和接口来完成所有操作。因此,我们不能严格说一个比另一个更好。最终,选择哪个取决于个人的选择。您将逐渐发展出自己使用它们的风格。

接下来,您可以查看Typescript vs. Javascript

Happy Coding 🙂

类似文章