跳到主要内容

Type 和 Interface 的区别

根据官方文档的入门教学, interface能满足我们的大部分需要,直到它不能解决我们的需求时才考虑type

You’ll see that there are two syntaxes for building types: Interfaces and Types. You should prefer interface. Use type when you need specific features.
https://www.typescriptlang.org/play/?e=83#example/types-vs-interfaces

来看看这个官方的 Playground 里提到的几点都是什么:

大部分情况下两者都一样

我们在日常开发中可能会觉得两者都差不多,事实也确实如此:

type BirdType = {
wings: 2;
};

interface BirdInterface {
wings: 2;
}

const bird1: BirdType = { wings: 2 };
const bird2: BirdInterface = { wings: 2 };
//这是合法的
const bird3: BirdInterface = bird1;

继承写起来也差不多:

type Owl = { nocturnal: true } & BirdType;
type Robin = { nocturnal: false } & BirdInterface;

interface Peacock extends BirdType {
colourful: true;
flies: false;
}
interface Chicken extends BirdInterface {
colourful: false;
flies: false;
}

let owl: Owl = { wings: 2, nocturnal: true };
let chicken: Chicken = { wings: 2, colourful: false, flies: false };

// That said, we recommend you use interfaces over type
// aliases. Specifically, because you will get better error
// messages. If you hover over the following errors, you can
// see how TypeScript can provide terser and more focused
// messages when working with interfaces like Chicken.

owl = chicken;
chicken = owl;

这里官方提到,建议你优先使用 interface 的另一个好处是,可以提供更好的错误提示:

先来看猫头鹰 Owl 类型,它是由 BirdType 继承而来,而它的报错看起来就像这个:

Type 'Chicken' is not assignable to type 'Owl'.
Property 'nocturnal' is missing in type 'Chicken' but required in type '{ nocturnal: true; }'.

再看看鸡 Chicken 类型,它是由 BirdInterface 继承而来,而它的报错更清晰明了:

Type 'Owl' is missing the following properties from type 'Chicken': colourful, flies

Interface 可以被重复申明

One major difference between type aliases vs interfaces are that interfaces are open and type aliases are closed. This means you can extend an interface by declaring it a second time.

interface Kitten {
purrs: boolean;
}
//这会导致合并但是合法
interface Kitten {
colour: string;
}

// In the other case a type cannot be changed outside of
// its declaration.

type Puppy = {
color: string;
};
//这是不合法的,TS会尖叫:Duplicate identifier 'Puppy'
type Puppy = {
toys: number;
};

这里需要注意的是,interface 重复申明的情况下,类型会合并,不会覆盖,事实上如果你覆盖其中的类型会发生报错:

interface Kitten {
purrs: boolean;
}

interface Kitten {
colour: string;
//这不行,TS报错:
//Subsequent property declarations must have the same type. Property 'purrs' must be of type 'boolean', but here has type 'number'
purrs: number;
}

公开导出的类型最好是 interface

on your goals, this difference could be a positive or a negative. However for publicly exposed types, it's a better call to make them an interface.