The quick guide to the best TypeScript tips: Interfaces

Updated: Jan 31

Te explicamos qué son las interfaces, cómo crearlas y las reglas detrás de ellas. 2da parte de la miniserie de Melt: Quick Guide - TypeScript! 🆃🆂 ✨

Recopilamos para ti algunos tips útiles de TypeScript!



Antes de seguir leyendo, recuerda que este post hace parte de una miniserie y probablemente para algunos ejemplos necesites ponerte en contexto con el post anterior, te invitamos a revisarlo: The quick guide to the best TS tips: Vars & Types.


La interfaz es una estructura que define la sintaxis de los tipos objeto, es decir, básicamente cualquier tipo de valor que posea propiedades. Más adelante revisaremos varios ejemplos que darán más claridad.


TypeScript

TALK DE LA SEMANA



Declarar tipos personalizados

En TypeScript podemos usar Type o Interface para describir la estructura de los objetos. Un ejemplo de tipo personalizado es el tipo Persona básico en TypeScript y de acuerdo con los requisitos puedes agregarle o no parámetros al tipo.


Usando type puedes agregar el tipo así:

type Persona = {name: string};

El Sistema de Tipos es responsable de verificar el tipo de datos de cualquier valor y, muestra los diferentes tipos de datos que admite TypeScript, estos se dividen en tres secciones principales: Any Type, Built-In-Type y User-Defined Type.


// Creando un Type 
type Persona { 
  name: string;
} 
  
type Persona { 
  age: number; 
} 
  
// Usando el Type con los datos 
const readPersona: Persona = { 
  name: "Juan",
  age: 39
};
  
console.log(readPersona); // Duplicate indentifier 'Persona' error.
 

Para crear una interfaz, debes definir la estructura básica del nuevo tipo con interface y se pueden incluir propiedades o métodos utilizando una arrow function:

interface Persona { 
    name: string; 
    age: number; 
}

Como es un requerimiento sintáctico que todas las entidades deben seguir, si creamos un nuevo objeto de tipo Persona este puede contener la declaración de los miembros.

// Creando una Interfaz 
interface Persona { 
  name: string; 
  age: number;
} 
  
interface Persona { 
  address: string; 
} 
  
// Usando la Intefaz fusionada  
const readPersona: Persona = {  
  name: "Juan", 
  age: 39, 
  address: "Kra1"
}; 

console.log(readPersona); // name: "Juan", age: 39, address: "Kra1"

Características

En una interfaz Persona de tres propiedades name, age y address:

  1. Una variable "otraPersona" se puede declarar de tipo Persona, si sus propiedades siguen la misma estructura que Persona.

  2. Por lo que, si se asigna un tipo diferente TypeScript mostrará un error. Persona sólo se podrá asignar a un objeto con: name tipo string, age tipo number y address tipo string.

  3. De igual manera, el compilador de TypeScript también mostrará un error si hay algún cambio en el nombre de las propiedades.

TypeScript utiliza interfaz para siempre garantizar la estructura correcta del objeto ✔


Type

Interface

Es una colección de tipos de datos

Funciona como una forma de sintaxis

Sirve para crear un nuevo nombre para tipos

Sirve como forma de definir las entidades

No admite el uso de objetos

Es compatible con objetos

No funcionan dos tipos del mismo nombre

Dos interfaces de mismo nombre se fusionan


Interfaz: Propiedades Opcionales

Interface te permite agregar una propiedad a la estructura pero esta vez de forma opcional, esto nos abre posibilidades de trabajo para sólo algunos objetos específicos. Por ejemplo, en el caso del objeto Persona, podemos agregar una propiedad de middleName, pero sólo a los que tienen segundo nombre.


En este casos, se agrega un signo de interrogación (?) después del nombre de la propiedad para establecerla como opcional al momento de la declaración de la interfaz.

interface Persona { 
  name: string;
  middleName?: string; // propiedad opcional
  age: number;
  address: string;
}

let unaPersona: Persona = { 
  name: "Juan", 
  age: 39, 
  address: "Kra1"
}

let otraPersona: Persona = { 
  name: "Carlos",
  middleName: "Arturo",
  age: 28,
  address: "Kra2 #3-1"
}

TypeScript no marcará un error por propiedades faltantes o desconocidas.



Function Type

Para describir una función implementamos la expresión de tipo function, su sintaxis es similar a las arrow functions:

function greeter(fn: (a: string) => void) {
  fn("Hello, World");
}

Donde la siguiente línea se refiere a:

fn: (a: string) => void 
// Función de 1 parámetro tipo cadena, sin retorno.

Al igual que con las declaraciones de funciones, si no se especifica el tipo del parámetro este será de tipo Any.

ⓘ El nombre del parámetro es obligatorio. Si no se especifica bien, por ejemplo: fn (string) => void, se entenderá que, existe 1 parámetro llamado string tipo Any.

Te contamos más sobre las funciones:

Si existe algún error en el reproductor, puedes ver el video en el siguiente LINK.



Interfaz: Indexable Types

TypeScript te permite agregar propiedades adicionales a objetos específicos con index signature en la declaración de la interfaz, donde podemos especificar propiedades para los diferentes objetos que se están creando.


Por ejemplo,

interface Persona { 
  name: string;
  middleName?: string;
  age: number;
  address: string;
 [extraProp: string]: any  // index signature
}

let otraPersona: Persona = { 
  name: "Carlos",
  middleName: "Arturo",
  age: 28,
  address: "Kra2 #3-1",
  thirdName: "Enrique"
}

Dado que cada Persona podría tener su propia cantidad de nombres, imagina crear un posible 3er, 4to o 5to nombre con los opcionales. No parece ser una buena idea...


Como dato curioso, en la Registraduría Nacional (Datos del 2010) existe una lista con los nombres más largos en Colombia:


TypeScript generalmente crea un nuevo objeto al agregar la palabra new delante de una firma:

type SomeConstructor = {
  new (s: string): SomeObject;
};

function fn(ctor: SomeConstructor) {
  return new ctor("hello");
}

Algunos objetos, como el objeto de JavaScript Date, se pueden llamar con o sin new. Puede combinar llamadas y construir firmas en el mismo tipo:

interface CallOrConstruct {
  new (s: string): Date;
  (n?: number): number;
}

Interfaz: Read Only

Es importante definir a una propiedad como readonly solo cuando el objeto o el array se modifica al ser creado en la declaración de la interfaz.

interface Persona {
  readonly id: number;        // El ID no puede ser modificado
  name: string;
  ...
}
let otraPersona: Persona = { 
  id: 1104374623
}

otraPersona.id = 1045746159;   // Error 'id' is read-only


Conversión de Tipo

Cuando un tipo se define ampliando la interfaz de otro, la relación generada entre los dos nos da permiso para convertir objetos definidos en uno de ellos en otro.


Por ejemplo, usando un objeto de tipo Persona:

const newPersona: Persona={
  id: 456,
  name: "Manuel"
}

const convertedPersona = <Persona> newPersona;
const anotherconvertedPersona = newPersona as Persona;
  • Este código se compila sin errores.

  • Tiene sentido que esta conversión funcione porque newPersona tipo ya posee todos los campos definidos del tipo Persona.

  • Si intentamos acceder al campo de fabricante definido en el objeto antes de la conversión, genera un error porque el objeto convertido es de Persona.

  • Si se intenta acceder al nuevo campo que Persona anteriormente no tenía, regresa undefined.


Extending Types

Pueden existir algunos tipos que son versiones más específicas de otros tipos. Por ejemplo, para las direcciones usualmente es suficiente sólo pedir la calle, ciudad, país y dirección postal.

interface BasicAddress {
  name?: string;
  street: string;
  city: string;
  country: string;
  postalCode: string;
}

Pero si vives en un conjunto u edificio, será requerido solicitar la información asociada. Entonces este sería un caso de tipo específico:

interface AddressWithUnit {
  name?: string;
  unit: string;
  street: string;
  city: string;
  country: string;
  postalCode: string;
}

Sin embargo, también tuvimos que repetir todos los demás campos. Así que TypeScript te ofrece el poder extender el tu tipo original y agregar los nuevos campos usando extends:

interface AddressWithUnit extends BasicAddress {
  unit: string;
}

extends en una interfaz te permite copiar propiedades de otros tipos y añadir los nuevos. Son esto dejamos también de repetitir el tipo y aprovechar las relaciones.


Y en interfaces también puedes extender a múltiples tipos:

interface Colorful {
  color: string;
}
 
interface Circle {
  radius: number;
}
 
interface ColorfulCircle extends Colorful, Circle {}
 
const cc: ColorfulCircle = {
  color: "red",
  radius: 42,
};


Ejemplos

En el siguiente video, ejemplificamos casos de uso de interface, mencionados anteriormente:

Si existe algún error en el reproductor, puedes ver el video en el siguiente LINK.


En el próximo capítulo, aprenderemos más sobre las clases de TypeScript.

_________________________________________________________________________________________


¡Gracias por leer!

MeltStudio.co/blog

24 views

Join our newsletter to receive information about latest technologies trends and job offers

Thanks for subscribing!