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能更好地处理函数、复杂类型。能保证使用的时候,不能随意在上面添加属性。

支持的语法区别

extendsimplements只适用于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;

#TypeScript

SideEffect is a blog for front-end web development.
Code by Axiu / rss