持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第 5 天,点击查看活动详情
使用 interface
和 type
声明是表示给定数据结构的常用方法。
// 使用接口
interface Point {
x: number
y: number
}
// 使用类型别名
type Point = {
x: number
y: number
}
区别
TypeScript 中类型别名和接口之间的区别在过去更为明显,但随着 TypeScript 的最新版本,它们变得越来越相似。
以下是它们的一些区别。
对象/函数
两者都可以用来描述对象的结构或函数签名。但语法不同。
// 接口
interface Point {
x: number
y: number
}
interface SetPoint {
(x: number, y: number): void
}
类型别名
type Point = {
x: number
y: number
}
type SetPoint = (x: number, y: number) => void
其他类型
与接口不同,类型别名是数据类型的定义,可用于任何其他类型,例如:联合类型、交叉类型、原始类型、元组等。
// union
type PartialPoint = PartialPointX | PartialPointY
// object
type PartialPointX = { x: number }
type PartialPointY = { y: number }
// primitive
type Name = string
// tuple
type Data = [number, string]
// other
声明合并
与类型别名不同,一个接口可以定义多次,并将被视为一个接口(所有声明的成员都被合并)。
interface Point {
x: number
}
interface Point {
y: number
}
const p: Point = {
x: 1,
y: 2
}
而类型别名必须是唯一的,并且不允许合并声明,否则编译器将报错。
type Person = {
firstName: string
}
// Throw error: Duplicate identifier
type Person = {
lastName: string
}
能够合并接口声明是非常有用的。例如,当我们为一个外部库提供类型定义时,它不是完全用 TypeScript 创建的。
在这种情况下,如果缺少一些定义,我们可以通过声明合并来提供它们。
继承
两者都可以继承,但同样,语法不同。此外,请注意接口和类型别名不是相互排斥的。接口可以继承类型别名,反之亦然。
接口继承接口:
interface PartialPointX {
x: number
}
interface Point extends PartialPointX {
y: number
}
类型别名继承类型别名:
type PartialPointX = { x: number }
type Point = PartialPointX & { y: number }
接口继承类型别名:
type PartialPointX = { x: number }
interface Point extends PartialPointX {
y: number
}
类型别名继承接口:
interface PartialPointX {
x: number
}
type Point = PartialPointX & { y: number }
implement
关键字
类可以以完全相同的方式实现接口或类型别名。但是请注意,类和接口被视为静态蓝图。因此,它们不能实现/继承命名联合类型的类型别名。
interface Point {
x: number
y: number
}
class SomePoint implements Point {
x = 1
y = 2
}
type Point2 = {
x: number
y: number
}
class SomePoint2 implements Point2 {
x = 1
y = 2
}
type PartialPoint = { x: number } | { y: number }
// FIXME: 无法实现联合类型
class SomePartialPoint implements PartialPoint {
x = 1
y = 2
}
建议
要决定是使用类型别名还是接口,您应该仔细考虑和分析情况,您正在处理什么,具体的代码等。
结合上述它们之间的区别,以下是一些我认为不错的建议:
- 如果您希望定义一个变量类型,就用
type
,如果希望能够继承并约束,就用interface
- 如果您不知道该用哪个,建议使用
type
- 如果您是库的作者或为外部库创建类型定义,请使用
interface
,方便其他人也可以扩展它们
更多资料
Stack Overflow 有更多关于这方面的讨论,地址 👉 Interfaces vs Types in TypeScript。
本文首发 blog,如果喜欢或者有所启发,欢迎 Star
,对作者也是一种鼓励。