Muchos desarrolladores se confunden al elegir entre una interfaz TypeScript o un tipo. Esto es probablemente porque son muy similares con diferencias menores.
Exploremos algunas prácticas sensatas y valores predeterminados, mientras descubrimos algunas gemas ocultas en el lenguaje TypeScript y respondemos a la pregunta «¿Debería usar una interfaz o un tipo?»
¡Una vez que hayas terminado, echa un vistazo a mi otro artículo sobre TypeScript Interfaces vs Clases!
Aquí está mi regla: Para casos de uso como la creación de nuevos tipos a través de cosas como primitivas, tipos de unión y tipos de tupla, prefiero usar la palabra clave type
. Para cualquier otra cosa (objetos/arreglos), es un interface
.
Un interface
es extremadamente útil cuando se trata de estructuras de datos ya que son una representación muy visual (aunque también lo es type
, esta es típicamente mi preferencia). Está completamente bien elegir un type
para tus objetos y arrays también.
Sin embargo, vamos a descubrir algo más sobre Tipos vs Interfaces en TypeScript para que puedas tomar una decisión más informada.
Objetos: Tipo vs Interfaz
Típicamente definiríamos una estructura de datos para modelar un tipo contra nuestras variables y argumentos de función previstos. La mayoría de las veces una estructura de datos es un array o un objeto que puede contener algunos métodos.
Creemos un objeto como una interfaz (enfoque recomendado):
interface Milkshake { name: string; price: number; getIngredients(): string;}
Aquí, prefiero usar una interfaz porque está claro que es una interfaz y no una variable con datos asignados – una buena ganancia de legibilidad. Estamos usando name
y price
para permitir establecer registros y getIngredients
como nuestra llamada al método.
🎉 ¡Descárgalo gratis!
¿Listo para ir más allá de ForEach? Toma confianza con los métodos avanzados: Reduce, Find, Filter, Every, Some y Map.
- Entiende completamente cómo manejar las Estructuras de Datos de JavaScript con operaciones inmutables
- 31 páginas de sintaxis en profundidad, ejemplos del mundo real, consejos y trucos
- Escribe una lógica de programación más limpia y mejor estructurada en 3 horas
Como bono extra, también te enviaremos algunas golosinas extra a través de algunos correos electrónicos adicionales.
Cuando comparamos esto con un tipo – podría ser fácilmente confundido como un objeto real debido a la asignación =
:
type Milkshake = { name: string; price: number; getIngredients(): string;};
Esto es sólo mi pequeña preferencia por elegir un interface
sobre el uso de un type
aquí – pero eres libre de usar la palabra clave type
si lo deseas.
Intersección: Tipo vs Interfaz
¡Interseccionar simplemente significa combinar uno o más tipos! Este patrón se puede lograr utilizando tanto un interface
o type
.
Supongamos las siguientes interfaces, te mostraré cómo podemos intersecar un interface
y type
:
interface MilkshakeProps { name: string; price: number;}interface MilkshakeMethods { getIngredients(): string;}
Con una interfaz, intersecaríamos utilizando la palabra clave extends
. Estoy usando múltiples interfaces para mostrarte cómo extender (heredar) en una interfaz final Milkshake
que contiene todas las propiedades y métodos definidos en otro lugar:
// { name: string, price: number, getIngredients(): string }interface Milkshake extends MilkshakeProps, MilkshakeMethods {}
Ahora podemos usar Milkshake
donde queramos y podemos beneficiarnos de tener name
, price
y getIngredients
en una sola referencia de interfaz.
Así es como haríamos lo mismo con un type
e intersectando los tipos a través de &
:
// { name: string, price: number, getIngredients(): string }type Milkshake = MilkshakeProps & MilkshakeMethods;
Yo recomendaría usar un type
en lugar de un interface
cuando quieras intersectar tipos. Usando extends
se siente un poco más verboso y no tan claro para leer y siento que esto es para lo que la palabra clave type
fue hecha.
También es súper fácil simplemente combinar más tipos con type
. Me parece que el código es más claro que el uso de extends
con interfaces.
Las interfaces también son limitadas – el alias type
puede ser utilizado para tipos más complejos como tuplas, primitivas, uniones y otros más:
// { name: string, price: number, getIngredients(): string }type Milkshake = MilkshakeProps & { getIngredients(): string };
Primitivas: Tipo vs Interfaz
Hablemos de tipos primitivos. Sí, cadenas, números, etc. Sólo puedes asignar un tipo primitivo a un alias type
:
type MilkshakeName = string;interface Milkshake { name: MilkshakeName; price: number;}
Si necesitas usar una primitiva, usa una type
. Las interfaces no sirven aquí para un solo valor ya que la sintaxis no lo soporta.
🎉 ¡Descarga gratis!
¿Listo para ir más allá de ForEach? Toma confianza con los métodos avanzados: Reduce, Find, Filter, Every, Some y Map.
- Entiende completamente cómo manejar las Estructuras de Datos de JavaScript con operaciones inmutables
- 31 páginas de sintaxis en profundidad, ejemplos del mundo real, consejos y trucos
- Escribe una lógica de programación más limpia y mejor estructurada en 3 horas
Como bono extra, también te enviaremos algunas golosinas extra a través de algunos correos electrónicos adicionales.
Para la mayoría de los casos, sin embargo, sería más fácil simplemente utilizar el valor primitivo directamente:
interface Milkshake { name: string; price: number;}
¡No compliques demasiado tu código!
Clases: Tipo vs Interfaz
Independientemente de que hayas elegido un type
o un interface
la forma en que lo usamos con una clase es la misma:
type Size = { size: string};interface Milkshake { name: string; price: number; getIngredients(): string;}class Order implements Size, Milkshake { // Size size = 'large'; // Milkshake name = 'Vanilla'; price = 399; getIngredients() { return ; }}
Las clases no admiten implementar/extender tipos de unión, porque se consideran planos estáticos. Esto significa que tienes que ser súper explícito sobre cada tipo que implementas, ya que no puede ser dinámico o cambiar ahora mismo debido a las limitaciones de TypeScript.
¡Aprende más sobre TypeScript Interfaces vs Clases!
Funciones: Tipo vs Interfaz
Típicamente crearía una función usando el alias type
ya que la mayoría de las veces querríamos escribir una función anónima:
type IngredientsFn = () => string;const getIngredients: IngredientsFn = () => ;
Sin embargo, si usar un interface
para esto sería más tu estilo, aquí está cómo hacerlo:
interface IngredientsFn { () => string;}
Se siente un poco torpe en comparación con el uso de type
, pero de nuevo ambos son completamente válidos TypeScript y no hay ninguna diferencia cuando el código se compila.
Cuándo no usar un Type
Ahora que hemos explorado las diversas comparaciones y enfoques recomendados, es el momento de hablar de la Fusión de Declaraciones, una característica de TypeScript que se aplica sólo a interface
y que sería una razón para elegir un interface
sobre un type
.
Para fusionar tipos usando type
, tendríamos que hacer algo así y crear un nuevo type
final:
type MilkshakeProps = { name: string; price: number;};type MilkshakeMethods = { getIngredients(): string;};type Milkshake = MilkshakeProps & MilkshakeMethods;
Nuestro type Milkshake
es ahora un alias de tipo de MilkshakeProps
y MilkshakeMethods
. Nótese que para lograr este comportamiento hemos tenido que crear Milkshake
, dándonos 3 alias de tipo individuales.
Con las interfaces, hay de hecho un enfoque más inteligente (algunos podrían decir que demasiado inteligente) llamado fusión de declaraciones.
Podemos lograr una fusión de declaraciones simplemente declarando el mismo interface
dos veces en el mismo ámbito (esto podría ser a través de la importación de la interfaz de otro módulo, o declarándola localmente junto a otra interfaz):
// declared once...interface Milkshake { name: string; price: number;}// declared again the same, it works!interface Milkshake { getIngredients(): string;}// { name: string, price: number, getIngredients(): string }const milkshake: Milkshake = { name: 'Banana', price: 399, getIngredients() {...}};
¡Milkshake ahora contiene name
, price
y getIngredients
! Sin embargo, ¿es buena la fusión de declaraciones? Sinceramente, no soy un fanático y siento que podría conducir a más daño que bien. Yo compondría tus tipos a través de type
en lugar de usar la fusión de declaraciones – pero al menos ahora conoces la(s) principal(es) diferencia(s).
Conclusión
¡Así que ahí lo tienes! Las principales diferencias entre Tipos e Interfaces en TypeScript.
Para recapitular, con algunas preferencias personales también, me quedaría con un interface
para los objetos y usaría la palabra clave type
alias para componer nuevos tipos sobre la marcha. Estos nuevos tipos podrían ser incluso de interfaces u otros tipos como tuplas, uniones y tipos de intersección. Hay un montón de posibilidades, pero mediante la comprensión de los enfoques podemos empezar a elegir la herramienta adecuada.
Por la mayor parte, las interfaces y los tipos son más o menos lo mismo, además de unas pocas diferencias cubiertas aquí. Espero que hayas disfrutado de la lectura.
Si te tomas en serio tus habilidades con TypeScript, tu siguiente paso es echar un vistazo a mis cursos de TypeScript, te enseñarán los fundamentos completos del lenguaje en detalle, así como muchos casos de uso avanzados que necesitarás en el desarrollo diario de TypeScript.
¡Feliz codificación!