TypeScript中,interface和type使用上有什么区别?

TypeScript 是 JavaScript 的一个超集,通过为 JavaScript 提供类型系统和其他语言特性来增强 JavaScript 的功能(配合VSCode,代码提示真的丝滑)。TypeScript 可以在编译时进行类型检查,从而提供更好的代码可读性和可维护性,并且可以在开发过程中减少错误和调试时间),减少了很多低级语法错误,这类问题有时候排查好久才会发现,查到的时候往往会忍不住骂娘。

我使用TypeScript的时长差不多两年半了,在使用的初期,我便注意到在 TypeScript 中,interface 和 type 都可以用来定义对象的类型。

typescript 复制代码
// 使用 interface 定义对象类型
interface User {
  name: string;
  age: number;
}

// 使用 type 定义对象类型
type User = {
  name: string;
  age: number;
}

上面定义的两个User对象类型,效果是等效的,在声明对象类型,函数的参数和返回类型等最常用的场景中使用起来效果没有任何差别。

但是二者的使用方式其实还是有挺多区别,花几分钟了解之后,还是可以在小白面前装一下的。

哈哈,玩笑玩笑,最终还是为了更好地使用工具。

总结起来包括了6点,TypeScript的官方文档中也有部分描述,点击末尾原文链接可以跳转官方文档(这里提一句,TS的官方文档写得真好,强烈建议读英文原版文档,一开始可能有点慢,但是很快就适应过来了)。

1. interface 可以被类实现和扩展,而 type 不行

下面的例子中,用interface声明了Animal,用type声明了Animal2,当我试图实现(implements)Animal2的时候,就报错了。

typescript 复制代码
interface Animal {
  name: string;
  eat(): void;
}

type Animal2 {
  name: string;
  eat(): void;
}

class Cat implements Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  eat() {
    console.log(`${this.name} is eating.`);
  }
}
// 错啦,type定义的对象类型不能被实现
class Dog implements Animal2 {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  eat() {
    console.log(`${this.name} is eating.`);
  }
}

interface就是用来实现的,就像信任就是用来辜负的一样。

2. 同名interface 可以被合并,而 type 不行。

在同一作用域内定义了两个相同名称的 interface,TypeScript 会将它们合并为一个。但是如果定义了两个相同名称的 type,则会产生命名冲突错误。

css 复制代码
interface A {
  name: string;
}

interface A {
  age: number;
}

// A 接口被合并为 { name: string; age: number; }
const a: A = {
  name: 'Jack',
  age: 20
}

// Error: Duplicate identifier 'B'.
type B = {
  name: string;
}

type B = {
  age: number;
}

3. type可以用于声明组合类型和交叉类型,interface则不行

下面这个case就是用type声明了组合类型和交叉类型。

ini 复制代码
interface InterfaceA {
  key1: string;
}

interface InterfaceB {
  key2: number;
}

type UnionType = InterfaceA | InterfaceB;
type IntersectionType = InterfaceA & InterfaceB;

const obj1: UnionType = { key1: 'hello' }; // 符合 InterfaceA
const obj2: UnionType = { key2: 42 }; // 符合 InterfaceB
const obj: IntersectionType = { key1: 'hello', key2: 42 }; // 同时符合 InterfaceA 和 InterfaceB

4. type声明的对象类型可以拿来组合成新的对象类型,interface不行

ini 复制代码
type Animal = {
  name: string
}

type Bear = Animal & { 
  honey: boolean 
}

const bear = getBear();
bear.name;
bear.honey;

5. 在定义对象类型时,interface 和 type 的语法略有不同。interface 使用花括号 {},而 type 使用等号 =。

这点有点凑数,但是确实是新手日常写代码经常混淆的点

typescript 复制代码
// interface 使用花括号 {} 定义对象类型
interface User {
  name: string;
  age: number;
}
// type 使用等号 = 定义对象类型
type User = {
  name: string;
  age: number;
}

6. type可以给基本类型起别名,interface不行

go 复制代码
type StringTypeHAHAHHAHA = string;
// interface做不到

------分割线------------------------------------------------

列举出来一看,差别还是挺多的,但是这些点其实没有必要去记忆,因为TypeScript的工具链相当完善,不合适的用法编辑器都会有清晰的提示。

在实际应用中,除了功能性的刚性约束,更重要的是用类型去表达一个准确的语义,事实上许多复杂类型需要组合使用type和interface才能实现。

本文权当做了一个趣味探索,有其他关于TypeScript好玩的点,欢迎留言交流。

相关推荐
前端郭德纲1 小时前
浅谈React的虚拟DOM
前端·javascript·react.js
2401_879103682 小时前
24.11.10 css
前端·css
ComPDFKit3 小时前
使用 PDF API 合并 PDF 文件
前端·javascript·macos
yqcoder3 小时前
react 中 memo 模块作用
前端·javascript·react.js
优雅永不过时·4 小时前
Three.js 原生 实现 react-three-fiber drei 的 磨砂反射的效果
前端·javascript·react.js·webgl·threejs·three
神夜大侠6 小时前
VUE 实现公告无缝循环滚动
前端·javascript·vue.js
明辉光焱6 小时前
【Electron】Electron Forge如何支持Element plus?
前端·javascript·vue.js·electron·node.js
柯南二号7 小时前
HarmonyOS ArkTS 下拉列表组件
前端·javascript·数据库·harmonyos·arkts
wyy72937 小时前
v-html 富文本中图片使用element-ui image-viewer组件实现预览,并且阻止滚动条
前端·ui·html
前端郭德纲7 小时前
ES6的Iterator 和 for...of 循环
前端·ecmascript·es6