TypeScript的type和interface
2020年12月21日 • ... • ☕️ 2 min read
用Typescript开发的时候,什么写的最多?当然是interface,至于type,什么是type?
一般认为,Typescript的类型检查,因为定义完整,帮助省debug的时间,在开发期间就暴露出可能存在问题的点,比如参数类型转换问题,成员变量未定义问题。但是一般也就是用interface,很少会用到type。我想这并不是开发的惰性,而是单使用interface,已经足够,或者是因为,代码水平规模没到,选择使用type还是interface的程度。
官方文档里,二者区别在 Interfaces vs. Type Aliases
类型(type)和类型别名(type alias)
Typescript的类型(Type),指基础类型:Boolean、Number、String、Array、Tuple、Enum、Unknown、Any、Void、Null和Undefined、Never、Object。
通常,上面几种类型不用重新定义,即直接使用关键字即可。但是TS还有类型别名(Type alias)的概念。类型别名只是取个新名字,比如
type Num = number;
let hour: number = 10;
let minutes: Num = 10;
类型别名就和interface很像了,interface大部分的特性,type都支持。
最重要的区别是:type不能添加新属性,但是interface是能扩展的。这里的可扩展,指重复命名的时候,interface会在旧的基础上扩展,但是type会报重复定义的错误。
interface Window {
title: string
}
interface Window {
content: string
}
// Window {
// title: string,
// content: string
//}
type Window = {
title: string
}
type Window = {
content: string
}
// Error: Duplicate identifier 'Window'.
官方建议,尽量使用interface。为什么呢?
从二者的特点可以看出来,唯一区别是是否支持属性合并。所以,对于很确定的类型,比如和接口协商好的数据返回格式,函数参数确定的组合类型,可以使用type,但是interface也行。
拿常用的react举例:
当我们定义组件传入的props时,需要使用interface
interface IProps {
name: string;
code: number;
}
const Request: React.FC<IProps> = (props) => {
// ...
};
然后,想给这个组件添加成员函数,定义函数的传入、返回
type ReturnVal = (
val: string;
) => string;
const returnValue: ReturnVal = (args) => {
// ...
return str;
};
通常来说,interface处理简单类型的对象和方法,比如需要类实现的部分。可以扩展,适应复杂的使用场景。
type alias能更好地处理函数、复杂类型。能保证使用的时候,不能随意在上面添加属性。
支持的语法区别
extends
和implements
只适用于interface,不能用于type。
同名的interface会合并成一个
interface IA {
strA: string
}
interface IA {
strB: string;
}
// IA: {strA: string; strB: string}
type alias的&
操作符可以合并两个interface
interface IA {
strA: string
}
interface IB {
strB: string;
}
type Join = IA & IB;