TypeScript:接口与类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37233735/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
TypeScript: Interfaces vs Types
提问by jabacchetta
What is the difference between these statements (interface vs type)?
这些语句(接口与类型)之间有什么区别?
interface X {
a: number
b: string
}
type X = {
a: number
b: string
};
采纳答案by Binary Birch Tree
As per the TypeScript Language Specification:
Unlike an interface declaration, which always introduces a named object type, a type alias declarationcan introduce a name for any kind of type, including primitive, union, and intersection types.
与总是引入命名对象类型的接口声明不同,类型别名声明可以为任何类型的类型引入名称,包括原始类型、联合类型和交集类型。
The specification goes on to mention:
规范继续提到:
Interface typeshave many similarities to type aliases for object type literals, but since interface types offer more capabilities they are generally preferred to type aliases. For example, the interface type
interface Point { x: number; y: number; }
could be written as the type alias
type Point = { x: number; y: number; };
However, doing so means the following capabilities are lost:
An interface can be named in an extends or implements clause, but a type alias for an object type literal cannotNo longer true since TS 2.7.- An interface can have multiple merged declarations, but a type alias for an object type literal cannot.
接口类型与对象类型文字的类型别名有很多相似之处,但由于接口类型提供了更多功能,因此它们通常比类型别名更受欢迎。例如接口类型
interface Point { x: number; y: number; }
可以写成类型别名
type Point = { x: number; y: number; };
但是,这样做意味着会丢失以下功能:
接口可以在 extends 或 implements 子句中命名,但对象类型文字的类型别名不能从 TS 2.7 开始不再为真。- 一个接口可以有多个合并声明,但对象类型文字的类型别名不能。
回答by jabacchetta
2019 Update
2019年更新
The current answers and the official documentationare outdated. And for those new to TypeScript, the terminology used isn't clear without examples. Below is a list of up-to-date differences.
当前的答案和官方文档已过时。对于那些不熟悉 TypeScript 的人,如果没有示例,所使用的术语就不清楚了。以下是最新差异的列表。
1. Objects / Functions
1. 对象/函数
Both can be used to describe the shape of an object or a function signature. But the syntax differs.
两者都可用于描述对象的形状或函数签名。但语法不同。
Interface
界面
interface Point {
x: number;
y: number;
}
interface SetPoint {
(x: number, y: number): void;
}
Type alias
类型别名
type Point = {
x: number;
y: number;
};
type SetPoint = (x: number, y: number) => void;
2. Other Types
2. 其他类型
Unlike an interface, the type alias can also be used for other types such as primitives, unions, and tuples.
与接口不同,类型别名还可以用于其他类型,例如基元、联合和元组。
// primitive
type Name = string;
// object
type PartialPointX = { x: number; };
type PartialPointY = { y: number; };
// union
type PartialPoint = PartialPointX | PartialPointY;
// tuple
type Data = [number, string];
3. Extend
3. 扩展
Both can be extended, but again, the syntax differs. Additionally, note that an interface and type alias are not mutually exclusive. An interface can extend a type alias, and vice versa.
两者都可以扩展,但同样,语法不同。此外,请注意接口和类型别名不是互斥的。接口可以扩展类型别名,反之亦然。
Interface extends interface
接口扩展接口
interface PartialPointX { x: number; }
interface Point extends PartialPointX { y: number; }
Type alias extends type alias
类型别名扩展类型别名
type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };
Interface extends type alias
接口扩展类型别名
type PartialPointX = { x: number; };
interface Point extends PartialPointX { y: number; }
Type alias extends interface
类型别名扩展接口
interface PartialPointX { x: number; }
type Point = PartialPointX & { y: number; };
4. Implements
4. 实施
A class can implement an interface or type alias, both in the same exact way. Note however that a class and interface are considered static blueprints. Therefore, they can not implement / extend a type alias that names a union type.
类可以以完全相同的方式实现接口或类型别名。但是请注意,类和接口被视为静态蓝图。因此,它们不能实现/扩展命名联合类型的类型别名。
interface Point {
x: number;
y: number;
}
class SomePoint implements Point {
x = 1;
y = 2;
}
type Point2 = {
x: number;
y: number;
};
class SomePoint2 implements Point2 {
x = 1;
y = 2;
}
type PartialPoint = { x: number; } | { y: number; };
// FIXME: can not implement a union type
class SomePartialPoint implements PartialPoint {
x = 1;
y = 2;
}
5. Declaration merging
5. 声明合并
Unlike a type alias, an interface can be defined multiple times, and will be treated as a single interface (with members of all declarations being merged).
与类型别名不同,接口可以被定义多次,并将被视为单个接口(所有声明的成员都被合并)。
// These two declarations become:
// interface Point { x: number; y: number; }
interface Point { x: number; }
interface Point { y: number; }
const point: Point = { x: 1, y: 2 };
回答by Karol Majewski
回答by nickf
https://www.typescriptlang.org/docs/handbook/advanced-types.html
https://www.typescriptlang.org/docs/handbook/advanced-types.html
One difference is that interfaces create a new name that is used everywhere. Type aliases don't create a new name — for instance, error messages won't use the alias name.
一个区别是接口创建了一个到处都使用的新名称。类型别名不会创建新名称——例如,错误消息不会使用别名。
回答by Przemek Struciński
Examples with Types:
类型示例:
// create a tree structure for an object. You can't do the same with interface because of lack of intersection (&)
// 为一个对象创建一个树结构。由于缺少交集 (&),您不能对界面做同样的事情
type Tree<T> = T & { parent: Tree<T> };
// type to restrict a variable to assign only a few values. Interfaces don't have union (|)
// type 限制一个变量只能分配几个值。接口没有联合 (|)
type Choise = "A" | "B" | "C";
// thanks to types, you can declare NonNullable type thanks to a conditional mechanism.
// 由于类型,您可以通过条件机制声明 NonNullable 类型。
type NonNullable<T> = T extends null | undefined ? never : T;
Examples with Interface:
接口示例:
// you can use interface for OOP and use 'implements' to define object/class skeleton
// 您可以使用 OOP 接口并使用“实现”来定义对象/类骨架
interface IUser {
user: string;
password: string;
login: (user: string, password: string) => boolean;
}
class User implements IUser {
user = "user1"
password = "password1"
login(user: string, password: string) {
return (user == user && password == password)
}
}
// you can extend interfaces with other interfaces
// 你可以用其他接口扩展接口
interface IMyObject {
label: string,
}
interface IMyObjectWithSize extends IMyObject{
size?: number
}
回答by dmudro
In addition to the brilliant answers already provided, there are noticeable differences when it comes to extendingtypes vs interfaces. I recently run into a couple of cases where an interface can't do the job:
除了已经提供的精彩答案之外,在扩展类型与接口方面存在明显差异。我最近遇到了一些界面无法完成工作的情况:
回答by Liu Lei
the documentation has explained
文档已经解释了
- One difference is that interfaces create a new name that is used everywhere. Type aliases don't create a new name — for instance, error messages won't use the alias name.in older versions of TypeScript, type aliases couldn't be extended or implemented from (nor could they extend/implement other types). As of version 2.7, type aliases can be extended by creating a new intersection type
- On the other hand, if you can't express some shape with an interface and you need to use a union or tuple type, type aliases are usually the way to go.
- 一个区别是接口创建了一个到处都使用的新名称。类型别名不会创建新名称——例如,错误消息不会使用别名。在旧版本的 TypeScript 中,类型别名不能扩展或实现(也不能扩展/实现其他类型)。从 2.7 版开始,可以通过创建新的交集类型来扩展类型别名
- 另一方面,如果你不能用接口表达某种形状,而你需要使用联合或元组类型,类型别名通常是要走的路。