为了账号安全,请及时绑定邮箱和手机立即绑定

TypeScript中类与接口

标签:
Html5


自ES6开始,JavaScript中已经有了类,TypeScript中类存在的时间甚至更长。然而TypeScript中也有接口的概念,在代码中添加类型声明时,经常会出现这样的问题:


对于这种类型声明是使用接口还是使用类?


本文聚集TypeScript中接口和类概念比较,这样我们能很好地回答这个问题。


1.从示例开始

为了理解本文,下面先给一个示例:


fetch('https://test.com/foo/bar')

    .then((response) => {

        console.log(response.status) // Some HTTP status code, such as 200

    })

1

2

3

4

这里只是示意很常见的一个任务————从远程服务器获取数据,然后进一步处理数据。


如何现在使用TypeScript处理上面代码,它会对response进行类型推断得到any类型。因为通过代码无法分析其应该属于何种类型。


为了增加程序类型安全,我们需要给response增加显示类型声明,请看下面代码告诉TypeScript编译器:


fetch('https://test.com/foo/bar')

    .then((response : Response) => {

        console.log(response.status) // Some HTTP status code, such as 200

    })

1

2

3

4

现在再回想前面提到的问题,新的Response应该被定义为interface还是class?


2. 接口

TypeScript检查程序不同类型时,其中关键方法是使用“鸭子方法”。


如果看起来像鸭子,叫起来像鸭子,那就是一个鸭子


也就是说,我们决定什么能被类型化一种特定类型,主要看起是否有需要特性/结构/形状(后面就称为形状)。在TypeScript中,interface是用于给这种特定形状事物赋予名称的一种方法,后面在程序中可以通过名称引用它。


下面使用duck进行类比,使用接口进行定义:


// A duck must have...

interface Duck {

    //  `hasWings` property with the value `true` (boolean literal type)

    hasWings: true

    //  `noOfFeet` property with the value `2` (number literal type)

    noOfFeet: 2

    //  `quack` method which does not return anything

    quack(): void

}

1

2

3

4

5

6

7

8

9

有了Duck类型,我们在代码中可以其定义duck实例(通过实现Duck接口):


// 可以通过编译

const duck: Duck = {

    hasWings: true,

    noOfFeet: 2,

    quack() {

        console.log('Quack!')

    },

}


// 下面这句代码不能通过编译

const notADuck: Duck = {}

// The TypeScript compiler would tell us

// "Type '{}' is not assignable to type 'Duck'.

// Property 'hasWings' is missing in type '{}'."

1

2

3

4

5

6

7

8

9

10

11

12

13

14

接口可以帮助TypeScript在编译时捕获代码潜在问题,但有其还有更多重要特性:


接口仅用于编译时,编译后被即被删除,接口不会输出至最终的JavaScript代码中。


让我们通过接口来定义Response来完成本节:


interface Response {

    status: number // Some HTTP status code, such as 200

}


fetch('https://test.com/foo/bar')

    .then((response: Response) => {

        console.log(response.status)

    })

1

2

3

4

5

6

7

8

如果现在运行TypeScript编译器,不会有错误,当然环境中有fetch API,输出的JavaScript代码为:


fetch('https://test.com/foo/bar')

    .then(function (response) {

    console.log(response.status);

});


1

2

3

4

5

我们看到编译时定义的类型没有影响运行时程序,这就是TypeScript神奇的接口功能!


3. 类

现在我们重新使用类定义Response:


class Response {

    status: number // Some HTTP status code, such as 200

}


fetch('https://test.com/foo/bar')

    .then((response: Response) => {

        console.log(response.status)

    })

1

2

3

4

5

6

7

8

我们仅把interface改为class,这时TypeScript编译没有错误,保证了类型安全,实现效果一样。但真正不同的是编译后的JavaScript代码。与interface不同,class也是JavaScript的结构体,但其包括更多信息。最大的差异是类提供行为的实现,不仅仅是形状属性。


下面我们看TypeScript编译后的代码:


var Response = (function () {

    function Response() {

    }

    return Response;

}());

fetch('https://test.com/foo/bar')

    .then(function (response) {

    console.log(response.status);

});

1

2

3

4

5

6

7

8

9

差异是类被编译成ES5函数形式,但我们并不需要这些代码。如果开发大型应用,使用重复使用这种模式声明类型,会导致应用中增加大量额外代码。


4. 总结

如果创建类型描述API的返回值,使用接口比较合适。与类不同,接口在编译后被完全删除,不会在JavaScript中增加不必要的代码。如果以后需要对接口的实现进行扩展,很容易将其转换成完整的类。

————————————————



点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消