文章首发javascript
原文: Interface vs Type alias in TypeScript 2.7html
译者注:java
常常有人在网上,在工做中,甚至在滑板公园询问我,在Typescript中定义编译时类型的类型别名和interface有什么区别。ios
我之前作的第一件事就是让他们去看Typescript的手册。。。git
不幸的是在大多数时候,他们不能找到他们想要找到的东西(隐藏在“高级类型”部分)。即便你能找到它,这个信息描述的是过期的(描述的行为指针对Typescript@2.0.x版本)。github
好消息各位!你没必要在看了,这篇文章是关于什么时候使用interface或类型别名的最新描述和风格指南。typescript
"类型别名 能够和interface关键字同样,然而他们有一些细微的差异。"
复制代码
这是对的bash
*interface*可以建立一个新的类型,*类型别名*不能建立一个新的类型
--例如:错误信息不能使用*类型别名*
复制代码
这是不对的!(自从Typescript 2.1开始)函数
咱们分别经过类型别名和interface定义编译时类型Point,而且实现使用interface和类型别名的类型参数实现两种getRectangleSquare
。ui
类型别名 和 interface 声明的Point
使用类型别名和interface定义getRectangleArea函数的参数
类型别名 和 interface声明的有相同的错误
两个相同的错误以下:
// TS Error:
// Interface:
Argument of type '{ x: number; }' is not assignable to parameter of type 'PointInterface'. Property 'y' is missing in type '{ x: number; }'.
// Type alias:
Argument of type '{ x: number; }' is not assignable to parameter of type 'PointType'. Property 'y' is missing in type '{ x: number; }'.
复制代码
"第二个更加剧要的重要的区别是类型别名不能被继承或者实现"
复制代码
这个一样也是错的
咱们可以经过一个interface继承类型别名:
interface 继承类型别名
或者咱们使用类型别名来实现类:
类实现类型别名。
或者一个类可以实现继承了类型别名的interface
ThreeDimension 继承了PointType。PointType是类型别名声明的。
咱们也能经过组合类型别名和interface去实现类。
class 实现了interface和类型别名
"3. 类型别名 不能继承/实现 其余的类型别名"
复制代码
固然这个也是错误的
类型别名能经过交叉类型运算符**&**扩展interface或者任意有效的Typescript类型(它相似字典或者javascript对象,非原始类型)。
类实现了具备交叉类型的*类型别名*
咱们也能利用映射类型实现interface和类型别名的各类类型转换。
让咱们经过Partial映射类型把Shape和Perimeter变为可选的。
类实现了经过交叉运算符和类型映射定义的*类型别名*。`perimeter()`和`area()`是可选的以致于咱们不必在类中去实现他们。
弱类型检测也正常工做
弱类型检测定期望的同样工做。
你可能偶尔想要定义一个能够充当一个具备额外属性对象或函数的对象。
咱们这里讨论的是定义函数(可执行对象),和该函数的静态属性。
当与第三方库进行交互时,能够看到这种模式,这充分描述了类型的“全貌”
混合类型的定义和实现。
它和类型别名同样工做!
经过类型别名定义混合类型。
可是有一个很是微妙的不一样。你将要在IDE中获得具体的类型信息去代替Counter类型。
使用类型别名和混合类型的interface的区别。
一般一个好的实践,是将咱们的混合定义分为两个部分:
可调用对象(函数)类型别名
静态属性对象描述
这将要在编译的时候触发一个错误:
第一点不一样——联合运算符定义的类型不能被实现
这彻底有道理!一个图纸不能实现两个结构类型中的一个,因此在这方面没有什么好惊讶的。
复制代码
类型别名联合使用用于定义对象是有意义而且有效的。因此下面会在编译时报一个错误,由于对象必须去定义perimeter()
和area()
两个中的一个。
联合类型——正确的使用对象字面量
第二个不一样——联合定义类型不能被`interface`继承
一样,这个类的实现类似, interface
是一个“静态”图纸——它不能实现两个结构中的一个,因此它不能被联合类型合并继承。
interface有声明合并,可是类型别名没有。
什么是声明合并?
你能定义屡次相同的interface,这些定义将要合并为一个。
声明合并
这种方式对于类型别名就不成立,由于类型别名是独一无二的实体(对于全局和模块域)。
第三个不一样——类型别名不支持声明合并。
当咱们为没有使用Typescript创做的库写第三方环境定义的时候,经过interface的声明合并是很是重要的,若是一些定义没有的话,使用者能够选择性的扩展它。
若是咱们的库是使用Typescript写的,而且自动生成环境定义则一样使用。
这是惟一的用例,你应该老是使用interface而不是类型别名。
通常的,你要使用的一致就能够(不管使用类型别名仍是interface),就我我的而言,我仍是推荐使用类型别名:
type Props = {}
// BAD
interface Props extends OwnProps, InjectedProps, StoreProps {}
type OwnProps = {...}
type StoreProps = {...}
// GOOD
type Props = OwnProps & InjectedProps & StoreProps
type OwnProps = {...}
type StoreProps = {...}
复制代码
在这遍文章中咱们学到了在Typescript 2.7中interface和类型别名的不一样。
有了这个,咱们得出在特定的场景中应该如何去定义编译类型的结论。
让咱们来回顾一下: