interface

接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。

  1. interface people {
  2. name: string;
  3. age: number;
  4. }
  5. let p:people = { name: '北鸟南游', age: 18 }

接口属性具有以下特性

可选属性

  1. interface people {
  2. name: string;
  3. age?: number;
  4. }

只读属性

  1. interface people {
  2. name: string;
  3. readonly age: number;
  4. }

定义无法确定属性的接口

  1. // 这个通过接口people创建的实例就可以添加其他属性
  2. interface people {
  3. name: string;
  4. age?: number;
  5. [propName: string]: any
  6. }

定义函数

  1. interface add {
  2. (a:number, b:number):number
  3. }

类接口

类实现接口

  1. interface Animal {
  2. legs: number,
  3. run(type:string):string;
  4. }
  5. class Dog implements Animal {
  6. legs: number;
  7. run(type:string):string{
  8. return 'run use' + this.legs + type;
  9. }
  10. }
  11. class Bird implements Animal {
  12. legs: number;
  13. run(type:string):string{
  14. return 'run use' + this.legs + type;
  15. }
  16. }

接口继承接口

  1. interface router{
  2. name: string;
  3. link: string;
  4. }
  5. interface componets{
  6. name: string;
  7. props: Record<string, unknown>
  8. }
  9. interface APP extends router, componets{
  10. time: Date;
  11. }

type类型别名

type相当于给类型起了一个名字

起别名并不是创建了一个新的类型。type可以作用于原始类型、联合类型、元组以及其他任何类型。

  1. type Name = string; // 基本类型
  2. type NameResolver = () => string; // 函数
  3. type NameOrResolver = Name | NameResolver; // 联合类型

类型别名可以是范型,可以添加类型参数,并且在类型别名的右侧传入。

  1. type Components<T> = { value:T }

可以在类型别名的属性里引用自己。

  1. type Components<T> = {
  2. value: T,
  3. comp: Components<T>
  4. }

可以用交叉类型使用,类型别名扩展属性使用&

  1. type LinkedList<T> = T & { next: LinkedList<T> };
  2. interface Dom {
  3. name: string;
  4. }
  5. var dom: LinkedList<Dom>;
  6. var s = dom.name;
  7. var s = dom.next.name;
  8. var s = dom.next.next.name;
  9. var s = dom.next.next.next.name;

相同点

都可以描述对象或者函数

interface定义对象或函数

  1. // 定义对象形式接口
  2. interface IPerson{
  3. name:string;
  4. age:number;
  5. }
  6. // 定义函数形式接口
  7. interface SetPerson{
  8. (name:string, age:number) : void;
  9. }

type定义对象或函数

  1. // 定义对象形式类型别名
  2. type TPerson = {
  3. name:string,
  4. age:number
  5. }
  6. // 定义函数形式类型别名
  7. type SetPerson = (name:string, age:number) : void;

其他type类型别名

类型别名比接口具有更大的适用性,可以定义基本类型、联合类型、元组。

  1. // primitive
  2. type Name = string;
  3. // object
  4. type PartialPointX = { x: number; };
  5. type PartialPointY = { y: number; };
  6. // union
  7. type PartialPoint = PartialPointX | PartialPointY;
  8. // tuple
  9. type Data = [number, string];
  10. // dom
  11. let div = document.createElement('div');
  12. type B = typeof div;

都允许扩展extends

interface 和 type 都可以拓展,并且两者并不是相互独立的,也就是说 interface 可以 extends type, type 也可以 extends interface 。 虽然效果差不多,但是两者语法不同。

interface extends interface

  1. interface Name {
  2. name: string;
  3. }
  4. interface User extends Name {
  5. age: number;
  6. }

type 扩展 type要使用&

  1. type Name = {
  2. name : string
  3. }
  4. type Person = Name & { age : number}

interface extends type

  1. type Name = {
  2. name:string
  3. }
  4. interface Person extends Name{
  5. age:number
  6. }

type 扩展 interface要使用&

  1. interface Name {
  2. name:string
  3. }
  4. type Person = Name & {
  5. age:number
  6. }

总结:interface扩展属性使用extends,type扩展属性使用&

应用

给type类型对象扩展属性,项目中应用

  1. import type { RouteConfig } from 'vue-router';
  2. // 给RouteConfig类型扩展属性
  3. const newRoutes : Array<RouteConfig & Record<string, any>> = []

将对象定义为类型

  1. const { dashboradCode } = routerParam;
  2. // dashboradCode是对象,通过typeof转化为类型
  3. const data: typeof dashboradCode = JSON.parse(routerParam);

不同点

type可以声明基本类型别名,联合类型,元组等类型

  1. // 基本类型别名
  2. type height = number;
  3. type name = string;
  4. // 联合类型
  5. interface Dog {
  6. wang()
  7. }
  8. interface Cat{
  9. miao()
  10. }
  11. type Pet = Dog | Cat;
  12. // 具体定义数组每个位置的类型
  13. type Pet = [ Dog, Cat ]

type语句中可以使用 typeof 获取实例的类型进行赋值

  1. // 当你想获取一个变量的类型时,使用 typeof
  2. let div = document.createElement('div');
  3. type B = typeof div

type其他操作

  1. type StringOrNumber = string | number;
  2. type Text = string | { text: string };
  3. type NameLookup = Dictionary<string, Person>;
  4. type Callback<T> = (data: T) => void;
  5. type Pair<T> = [T, T];
  6. type Coordinates = Pair<number>;
  7. type Tree<T> = T | { left: Tree<T>, right: Tree<T> };

interface 可以声明合并而 type 不行

声明接口时,如果接口已经存在,则属性会进行合并。就是说接口可以重复定义
type类型别名重复定义,会报错。

  1. interface Person{
  2. name:string
  3. }
  4. interface Person{
  5. age:number
  6. }
  7. // 接口Person最终类型name和age两个属性
  1. type language = {
  2. id:number;
  3. }
  4. // ts(2300)重复的标志错误
  5. type language = {
  6. name:string;
  7. }

type可以计算属性,接口不可以

type类型别名可以使用in关键字生成映射类型。

  • 类型变量key会依次绑定type的每个属性
  • 字符串字面量keys,包含了要迭代的属性名集合
  • 属性类型的定义 ```typescript type router = “name” | “props” | “children”; type Route = {

} const r: Route = { name: “route”, props: “up”, children: ‘many’ } // 定义接口使用in则报错 // interface Route { // [key in keys]: string // }

  1. <a name="eMowf"></a>
  2. ### 作为默认值导出
  3. 接口可以直接定义并导出
  4. ```typescript
  5. export default interface Config {
  6. name: string
  7. }

type类型别名不可以直接定义导出

  1. // 会报错
  2. // export default type Config1 = {
  3. // name: string
  4. // }
  5. //正确的使用类型别名方式,先定义再导出
  6. type Config2 = {
  7. name: string
  8. }
  9. export default Config2

类class可以实现接口和类型别名【除了联合类型外】

类型别名联合类型是不确定类型。类和接口被认为是静态的,实现联合类型时报错。

  1. interface Point {
  2. x: number;
  3. y: number;
  4. }
  5. class SomePoint implements Point {
  6. x: 1;
  7. y: 2;
  8. }
  9. type Point2 = {
  10. x: number;
  11. y: number;
  12. };
  13. class SomePoint2 implements Point2 {
  14. x: 1;
  15. y: 2;
  16. }
  17. type PartialPoint = { x: number; } | { y: number; };
  18. // FIXME: can not implement a union type
  19. // class SomePartialPoint implements PartialPoint {
  20. // x: 1;
  21. // y: 2;
  22. // }

参考文档:
https://pawelgrzybek.com/typescript-interface-vs-type/
https://stackoverflow.com/questions/37233735/interfaces-vs-types-in-typescript