¿Cuál es la diferencia entre estas declaraciones (interfaz vs tipo)?
interface X {
a: number
b: string
}
type X = {
a: number
b: string
};
¿Cuál es la diferencia entre estas declaraciones (interfaz vs tipo)?
interface X {
a: number
b: string
}
type X = {
a: number
b: string
};
Respuestas:
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 dado que 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.
interface Point { x: number; } interface Point { y: number; }
extends or implements
ya no es el caso. El tipo puede ser extendido e implementado por a class
. Aquí hay un ejemplo typescriptlang.org/play/…
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.
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;
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];
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; };
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;
}
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 };
type
o interface
? Todavía estoy confundido sobre cuándo debo usar uno u otro.
type
con ciertas limitaciones (y a partir de TypeScript 3.7 estas limitaciones también se han eliminado). Las interfaces pueden extender tipos. Las clases pueden implementar tipos. Además, presentar datos como una captura de pantalla de una tabla hace que sea completamente inaccesible para las personas con problemas de visión.
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.
// 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;
// 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
}
Además de las brillantes respuestas ya proporcionadas, existen diferencias notables cuando se trata de extender tipos frente a interfaces. Recientemente me encontré con un par de casos en los que una interfaz no puede hacer el trabajo:
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 nuevo nombre; por ejemplo, los mensajes de error no usarán el nombre de alias. En versiones anteriores de TypeScript, los alias de tipo no podían ampliarse ni implementarse (ni podían ampliar / 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.