myfreax

TypeScript: Interfaces vs Types对比与差别

与引入命名对象类型的接口声明不同,别名声明可以为任何类型的类型引入一个名称,包括原始,联合等。让我们看看Interfaces接口和Types区别与不同

3 min read
By myfreax
TypeScript: Interfaces vs Types对比与差别

个人建议总是优先使用interface 接口

什么时候使用Type?

  • 定义原始类型时
  • 定义元组tuple类型时
  • 定义函数时
  • 定义联合类型时
  • 当你需要重载对象的函数的时
  • 当你需要映射类型的优点时

什么时候使用接口

  • 对于上面的所有其它情况下个人推荐使用interface
  • 当你想使用合并声明的优点使用interface

原始类型Primitive types

最简单的方式查看type 和接口interface 的不同,只有type 可以用于原始类型的别名

type Nullish = null | undefined;
type Fruit = 'apple' | 'pear' | 'orange';
type Num = number | bigint;

这些都是不能用interfaces实现的。

💡当你需要定义一个原始类型的别名时,请使用type 关键词声明

元组类型Tuple types

Tuples只可以使用type 关键词声明:

type row = [colOne: number, colTwo: string];

💡 定义元组类型时使用type 关键字。

函数类型Function types

函数可以被typeinterface 修饰类型:

// via type
type Sum = (x: number, y: number) => number;

// via interface
interface Sum {
  (x: number, y: number): number;
}

由于可以使用两种方式都能实现相同的效果,因此在函数修饰类型上的方案是使用type ,因为它更易读更快捷。

💡 当修饰函数类型时使用 type

Union types 联合类型

联合类型只能通过type 关键词声明

type Fruit = 'apple' | 'pear' | 'orange';
type Vegetable = 'broccoli' | 'carrot' | 'lettuce';

// 'apple' | 'pear' | 'orange' | 'broccoli' | 'carrot' | 'lettuce';
type HealthyFoods = Fruit | Vegetable;

💡 当定义联合类型时使用type 关键词

Object types对象类型

一个对象在javascript中式key/value的映射,对象类型在typescript使用类型修饰,也是key/value映射。interfacetype 都可以修饰对象,那么我们应该使用type 还是interface 对于对象类型

交集与继承

使用types的组合我们可以做到下面操作:

type NumLogger = { 
  log: (val: number) => void;
}
type StrAndNumLogger = NumLogger & { 
  log: (val: string) => void;
}

const logger: StrAndNumLogger = {
  log: (val: string | number) => console.log(val)
}

logger.log(1)
logger.log('hi')

如果我们改用interfaces接口尝试:

interface NumLogger { 
    log: (val: number) => void;
}
interface StrAndNumLogger extends NumLogger { 
    log: (val: string) => void; 
};

StrAndNumLogger 声明将会给出一个错误:

在使用interfaces接口的情况下,子类的类型声明必须完全匹配父类,否则TS将会抛出上面的错误。

💡 当你尝试在对象上重载函数类型时,使用type 会更好。

Mapped object types映射对象类型

使用type 关键词,我们可以获得映射类型的所有好处,像下面的代码。

type Fruit = 'apple' | 'orange' | 'banana';

type FruitCount = {
  [key in Fruit]: number;
}

const fruits: FruitCount = {
  apple: 2,
  orange: 3,
  banana: 4
};

这是使用interfaces接口做不到的

type Fruit = 'apple' | 'orange' | 'banana';

// ERROR: 
interface FruitCount {
  [key in Fruit]: number;
}

💡 当需要映射类型的好处时使用type 关键词