[TS] interface 和 type 的区别

24 阅读2分钟

参考:

juejin.cn/post/707294…

ts.xcatliu.com/basics/type…

最近写 TS 项目遇到 type,心想自己好像一直在用 interface,感觉两者除了写法之外貌似没有什么区别,于是在此总结。

接口 interface

Typescript 中使用接口 interfaces 来定义对象的类型

  • 接口可用于对类的一部分行为进行抽象
  • 接口常用于对「对象的形状(Shape)」进行描述
  • 接口一般首字母大写,形如 IXxx
interface IPerson {
    name: string;
    age: number;
}
​
let tom: Person = {
    name: 'Tom',
    age: 25
};

类型别名 type

类型别名用来给一个类型起个新名字

  • 类型别名常用于联合类型
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
    if (typeof n === 'string') {
        return n;
    } else {
        return n();
    }
}
type EventNames = 'click' | 'scroll' | 'mousemove';
function handleEvent(ele: Element, event: EventNames) {
    // do something
}
​
handleEvent(document.getElementById('hello'), 'scroll');
// 没问题
handleEvent(document.getElementById('world'), 'dblclick');
// 报错,event 不能为 'dblclick'

相似之处

  • 都可以描述对象或函数,但语法不同
// type
type Point = {
  x: number;
  y: number;
};
type SetPoint = (x: number, y: number) => void;
​
// interface
interface IPoint {
  x: number;
  y: number;
}
interface ISetPoint {
  (x: number, y: number): void;
}
  • 都可以被继承
// interface 继承 inteface
interface IPerson{
    name:string
}
interface IStudent extends Person { stuNo: number }
​
// interface 继承 type
type Person{
    name:string
}
interface IStudent extends Person { stuNo: number }
​
// type 继承 type
type Person{
    name:string
}
type Student = Person & { stuNo: number }
​
// type 继承 interface
interface IPerson{
    name:string
}
type Student = Person & { stuNo: number }
  • 都可以实现 implements (类无法用 type 实现联合类型)
// interface implements
interface ICat{
    setName(name:string): void;
}
class Cat implements ICat{
    setName(name:string):void{
        // todo
    }
}
​
// type implements
type ICat = {
    setName(name:string): void;
}
​
class Cat implements ICat{
    setName(name:string):void{
        // todo
    }
}

不同之处

  • type 定义基本类型别名,但是 interface 无法定义
type userName = string
type stuNo = number
  • type 可以声明联合类型,例如
type Student = {stuNo: number} | {classId: number}
  • type 可以声明元祖类型
type Data = [number, string]
  • interface 声明合并,type 不可以
interface Person { name: string }
interface Person { age: number }
​
let user: Person = {
    name: "Tolu",
    age: 0,
};