typescript - multiple - Mecanografiado: Interfaces vs Tipos
typescript type vs interface (6)
¿Cuál es la diferencia entre estas declaraciones (interfaz vs tipo)?
interface X {
a: number
b: string
}
type X = {
a: number
b: string
};
Actualización 2019
Las respuestas actuales y la documentación oficial están desactualizadas. Y para aquellos nuevos en TypeScript, la terminología utilizada no está clara sin ejemplos. A continuación se muestra una lista de las diferencias actualizadas.
1. Objetos / funciones
Ambos se pueden usar para describir la forma de un objeto o una firma de función. Pero la sintaxis difiere.
Interfaz
interface Point {
x: number;
y: number;
}
interface SetPoint {
(x: number, y: number): void;
}
Escriba alias
type Point = {
x: number;
y: number;
};
type SetPoint = (x: number, y: number) => void;
2. Otros tipos
A diferencia de una interfaz, el alias de tipo también se puede usar para otros tipos, como primitivas, uniones y tuplas.
// primitive
type Name = string;
// object
type PartialPointX = { x: number; };
type PartialPointY = { y: number; };
// union
type PartialPoint = PartialPointX | PartialPointY;
// tuple
type Data = [number, string];
3. Extender
Ambos se pueden extender, pero de nuevo, la sintaxis difiere. Además, tenga en cuenta que una interfaz y un alias de tipo no son mutuamente excluyentes. Una interfaz puede extender un alias de tipo, y viceversa.
La interfaz extiende la interfaz
interface PartialPointX { x: number; }
interface Point extends PartialPointX { y: number; }
El alias de tipo extiende el alias de tipo
type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };
La interfaz extiende el alias de tipo
type PartialPointX = { x: number; };
interface Point extends PartialPointX { y: number; }
El alias de tipo extiende la interfaz
interface PartialPointX { x: number; }
type Point = PartialPointX & { y: number; };
4. Implementa
Una clase puede implementar una interfaz o un alias de tipo, ambos de la misma manera. Sin embargo, tenga en cuenta que una clase y una interfaz se consideran planos estáticos. Por lo tanto, no pueden implementar / extender un alias de tipo que nombre un tipo de unión.
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. Fusión de declaraciones
A diferencia de un alias de tipo, una interfaz se puede definir varias veces y se tratará como una única interfaz (con los miembros de todas las declaraciones fusionadas).
// 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 };
Ejemplos con tipos:
// crea una estructura de árbol para un objeto. No puede hacer lo mismo con la interfaz debido a la falta de intersección (&)
type Tree<T> = T & { parent: Tree<T> };
// escriba para restringir una variable para asignar solo unos pocos valores. Las interfaces no tienen unión (|)
type Choise = "A" | "B" | "C";
// gracias a los tipos, puede declarar tipos no anulables gracias a un mecanismo condicional.
type NonNullable<T> = T extends null | undefined ? never : T;
Ejemplos con interfaz:
// puedes usar la interfaz para OOP y usar ''implementos'' para definir el esqueleto de objeto / clase
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)
}
}
// puedes extender interfaces con otras interfaces
interface IMyObject {
label: string,
}
interface IMyObjectWithSize extends IMyObject{
size?: number
}
Según la especificación del lenguaje TypeScript :
A diferencia de una declaración de interfaz, que siempre introduce un tipo de objeto con nombre, una declaración de alias de tipo puede introducir un nombre para cualquier tipo de tipo, incluidos los tipos primitivos, de unión e intersección.
La especificación continúa mencionando:
Los tipos de interfaz tienen muchas similitudes con los alias de tipo para los literales de tipo de objeto, pero como los tipos de interfaz ofrecen más capacidades, generalmente se prefieren los alias de tipo. Por ejemplo, el tipo de interfaz
interface Point { x: number; y: number; }
podría escribirse como el alias de tipo
type Point = { x: number; y: number; };
Sin embargo, hacerlo significa que se pierden las siguientes capacidades:
Se puede nombrar una interfaz en una cláusula de extensiones o implementaciones, pero un alias de tipo para un literal de tipo de objeto ya no puedeser verdadero desde TS 2.7.- Una interfaz puede tener varias declaraciones fusionadas , pero un alias de tipo para un literal de tipo de objeto no puede.
la documentación ha explicado
- Una diferencia es que las interfaces crean un nuevo nombre que se usa en todas partes. Los alias de tipo no crean un nombre nuevo; por ejemplo, los mensajes de error no usarán el nombre de alias. En versiones anteriores de TypeScript, los alias de tipo no se podían extender ni implementar (ni podían extender / implementar otros tipos). A partir de la versión 2.7, los alias de tipo pueden ampliarse creando un nuevo tipo de intersección
- Por otro lado, si no puede expresar alguna forma con una interfaz y necesita usar un tipo de unión o tupla, los alias de tipo suelen ser el camino a seguir.
https://www.typescriptlang.org/docs/handbook/advanced-types.html
Una diferencia es que las interfaces crean un nuevo nombre que se usa en todas partes. Los alias de tipo no crean un nuevo nombre; por ejemplo, los mensajes de error no usarán el nombre del alias.