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

news/2024/7/23 23:22:37 标签: javascript, typescript

文章目录

      • 前言
      • 使用上的区别
      • 本质区别
      • 参考文档

前言

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

typescript">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.

比如:

typescript">// 定义各一个基本数据类型的别名
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)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由"当前方法和属性的集合"决定

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

typescript">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有所帮助。

参考文档

  • Promise A+
  • https://stackoverflow.com/questions/37233735/typescript-interfaces-vs-types
  • https://www.w3cschool.cn/doc_flow/flow-lang-nominal-structural.html
  • https://www.typescriptlang.org/docs/handbook/advanced-types.html#interfaces-vs-type-aliases
  • https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

http://www.niftyadmin.cn/n/1382699.html

相关文章

推荐几个前端开发插件

提高开发效率 简单的集成到了vue-cli生成的项目上 项目github地址 A Vue.js projectBuild Setup # install dependencies npm install# serve with hot reload at localhost:8080 npm run dev# build for production with minification npm run build# build for production an…

centos6.4下安装配置JDK+TOMCAT+MYSQL教程

2019独角兽企业重金招聘Python工程师标准>>> 一、系统环境和软件包 [rootlocalhost /]# uname -r 2.6.32-358.el6.x86_64 [rootlocalhost /]# cat /etc/centos-release CentOS release 6.4 (Final) 软件包 jdk-6u43-linux-x64-rpm.bin apache-tomcat-6.0.36.tar.gz …

QQ截图右键

1.CtrlAlt 2.右键 3.按下A键转载于:https://www.cnblogs.com/Bruce3555/p/5476622.html

二维树状数组的区间加减及查询 tyvj 1716 上帝造题的七分钟

详细解释见小结。http://blog.csdn.net/zmx354/article/details/31740985 #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <s…

git常用命令与概念汇总

设置记住用户名和密码 # --global如果不加则只针对当前项目 # 设置之后需要重新pull一下代码&#xff0c;然后提示输入用户名密码后会自动保存&#xff0c;从而实现记住用户名和密码的目的。 # 这样设置的用户名和密码是以明文的方式存储的。比如你安装了一个Npm包&#xff0c…

CentOS6 Shell脚本/bin/bash^M: bad interpreter错误解决方法

为什么80%的码农都做不了架构师&#xff1f;>>> 在windows下保存了一个脚本文件&#xff0c;用ssh上传到centos&#xff0c;添加权限执行nginx提示没有那个文件或目录。shell脚本放到/etc/init.d/目录下&#xff0c;再执行/etc/init.d/nginx&#xff0c;提示多了这…

[并查集] hihocoder 1158 质数相关

题目大意 题目链接&#xff0c;定义两个数\(a,b\)质数相关满足 \(ba\times p\), 且\(p\)是质数。给定数组&#xff0c;问最大质数无关子集大小。 算法思路 首先想到的是将每个数看作一个顶点&#xff0c;质数相关的两个数之间连边&#xff0c;求最大独立子集。但是最大独立子集…

Spring Cloud 微服务的那点事

在详细的了解SpringCloud中所使用的各个组件之前&#xff0c;我们先了解下微服务框架的前世今生。 单体架构 在网站开发的前期&#xff0c;项目面临的流量相对较少&#xff0c;单一应用可以实现我们所需要的功能&#xff0c;从而减少开发、部署和维护的难度。这种用于简单的增删…