从类型系统看TypeScript中 interface与type的区别

前言

在TypeScript中,有两中声明类型的方式。即InterfaceType

interface X {
    a: number
    b: string
}

type X = {
    a: number
    b: string
};

上面两种方式均可,所以很让人困惑,到底

  • 他们的区别是什么?
  • 什么时候该使用type,什么时候该使用interface?

使用上的区别

可能这个问题实在困扰人,所以TS的官方文档都做出了解释:

Because an interface more closely maps how JavaScript objects work by being open to extension, we recommend using an interface over a type alias when possible.
interface通过扩展(符合开闭原则)javascript的方式,更贴合javascript的工作机制。所以推荐使用interface而不是type

下图中,interface可以被扩展,而type不能,只能使用联合体创建一个新的type。

在这里插入图片描述

但紧接着文档中又说道,在某些场合比如联合类型或者元组类型,可能还是需要使用type

On the other hand, if you can’t express some shape with an interface and you need to use a union or tuple type, type aliases are usually the way to go.

比如:

// 定义各一个基本数据类型的别名
type Primitive = number | string | boolean | null | undefined

// 为元组声明类型
type IData = [string, number, number];

总结来说,从官方的意思是,尽量使用interface,在不得已的情况下再使用type

本质区别

官方的说法还算可以接受,但事实上,还有一个疑问,这也是本文想回答的问题,TypeScript为什么会有两种API去描述类型?

我个人感觉,这涉及到了TypeScript语言的类型系统本身,即TypeScript是一种Structual Type,而不是Nonimal Type。如果你了解Java,那么我可以告诉你TS中类型系统是区别于Java的。简单的说,Java中会通过接口的定义去描述类型(Nominal Type),而在TS中,类型的定义是依据于对象本身的行为。也就是所谓的鸭子类型(duck type)

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定

说的有些不好理解,不妨直接看下边的例子。

class Duck {
  quack() {
    console.log('鸭子在呱呱叫')
  }
  feathers() {
    console.log('鸭子有白色的羽毛')
  }
}
class Person {
  quack() {
    console.log('人在模仿鸭子叫')
  }
  feathers() {
    console.log('人穿着羽绒服....')
  }
}

const donald = new Duck();
const xiaoming = new Person();

const inTheForest = (duck: Duck) => {
  duck.quack()
  duck.feathers()
}

inTheForest(donald)
inTheForest(xiaoming) // 编译通过!!

在上面代码中,明明inTheForest函数需要一只鸭子,你却给了一个人。但因这个人看起来像鸭子,所以,编译通过了…

事实上这并不奇怪,因为JS就是这样的。比如promise中的resolve静态方法

返回一个状态由给定value决定的Promise对象。如果该值是thenable(即,带有then方法的对象),返回的Promise对象的最终状态由then方法执行决定

以上,即Promise.resolve函数的入参应该可以是一个Promise对象,但也可以是一个thenable的对象,即我不关心你是什么类型,只要你有then方法就行。和我不关心你是不是鸭子,只要你能呱呱叫就行是不是很类似?

实际上,你可以认为JS是一个运行时的鸭子类型语言。而TS仅仅是把这个类型检验放到了编译期

所以在TS中,对于任意一个对象,包括基本数据类型,都隐式的含有自己的类型,因为在编译过程中需要动态的检查类型。这个类型是编译系统的,并且他对外暴露出来了,就是type,所以type甚至可以表示基本数据类型。此外type的全名是叫type alias,即声明他只是对当前对象已经存在类型的一个别名。

所以你应该能明白为什么会有两个类型声明的方式

  • interface是正统的,静态类型语言都会包含的类型声明方式
  • type是TS作为structual类型语言附带给你赠品。

下面的例子进一步验证了type是是TS类型系统的类型别名。注意注释的说明
在这里插入图片描述
以上,希望本文对你理解interface和type有所帮助。

参考文档

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值