Si eres desarrollador web es de tu interés saber que es Typescript. Un lenguaje de programación que ha ganado bastante popularidad en los últimos años y al año 2022, ha sido adoptado como opción dentro de muchos frameworks. React, Angular y Vue entre otros.
Typescript es un superset de Javascript. En términos simples, es Javascript, pero con funcionalidades de tipado adicionales. ¿Pero qué funcionalidades? En términos simples, funcionalidades de tipado.
Ok… ¿y porqué querrías eso? Bueno una de las más grandes fortalezas de Javascript es al mismo tiempo una de sus más grandes debilidades. El ser un lenguaje debilmente tipado.
Javascript ofrece mucha versatilidad pero el precio a pagar es que es fácil generar código con poca claridad. De hecho una de las razones por las que hay tantos memes y chistes en la web acerca de la complejidad de Javascript es porque la mayoría de los desarrolladores tienen al menos una historia de terror en la que se encontraron un proyecto en Javascript hecho con las peores prácticas posibles.
Typescript viene a ofrecer las ventajas de un lenguaje fuertement tipado pero sin deshacerse de la versatilidad de Javascript. Es un punto medio que ha logrado que se gane una buena aceptación en los últimos años.
Sin embargo es probable que como es el caso de muchos, Typescript no haya llegado a tu vida porque tu lo hayas buscado. Por lo general la mayoría de los desarrolladores conocieron Typescript por una de 2 razones:
- Empezaron a aprender Angular (el cual por default usa Typescript)
- Entraron a un proyecto que ya estaba utilizando Typescript
Sea cual sea la razón, el punto es que la mayoría empieza a trabajar con Typescript sin tener la intención de aprender sobre el lenguaje como tal.
Esta clase de situaciones lleva a que la gente haga lo mismo en Typescript que en Javascript y eso al final…demerita el propósito del lenguaje.
Me he encontrado muchos proyectos que no usan ni siquiera las funcionalidades básicas de Typescript, por lo que aquí te muestro lo mínimo que en mi opinión deberías estar usando en tu proyecto.
Tipado Básico – (Typings)
let someText: string;
let someNumber: number;
let isFinished: boolean;
let namesList: string[];
let hobbiesList: Array<string>;
let person: {
name: string,
score: number,
classesList: string[],
isConfirmed: boolean
}
Empecemos por lo más obvio. Si no estas tipando tus variables, tus parámetros y tus valores de retorno, entonces no deberías estar usando Typescript.
¿Cuál es el punto de esto?
- Puedes verlo como una forma de documentar el código sin realmente hacer documentación.
- Te ayuda a detectar errores de tipo de datos más rápido
Con sólo leerlo tu equipo ya sabe el propósito de cada variable. Si pueden usarse para hacer operaciones aritméticas o para hacer concatenaciones. A su vez al compilar el código tu programa lanzará errores en caso de que hayas cometido algun error.
Esto ayuda increíblemente para objetos mas complejos como person
. Con solo ver la declaración de la variable y sin tener que inspeccionar más código sabemos que una persona tiene un nombre: name
, una lista de clases: classesList
, una puntuación: score
. y una especie de confirmación: isConfirmed
.
Al tener claro desde un inicio que tipo de dato aloja cada variable puedes ir obteniendo una idea más clara del modelo de negocio que atiende el sistema.
Alias Types/Interfaces
Esto simplemente puedes verlo como una forma de implementar tipado más complejo en tu código.
En el ejemplo anterior se ve que se puede definir el tipo de un objeto complejo abriendo las llaves y definiendo las propiedades dentro del mismo.
let person: {
name: string,
score: number,
classesList: string[],
isConfirmed: boolean
}
Es obvio que si vas a usar muchas veces una variable con ese tipo de objeto sería cansado escribir los mismo una y otra vez.
Para ello puedes definir una Interface o un Alias Type:
Interfaz – (Interface)
export interface BranchOffice {
branchId: number,
employees: Employee[]
}
export interface Employee {
employeeId: number,
name: string,
age: number,
position: string,
checkIn: () => boolean,
checkOut: () => boolean
}
Alias Type
export type Office = {
branchId: number,
employees: Employee[]
}
export type Employee = {
employeeId: number,
name: string,
age: number,
position: string,
checkIn: () => boolean,
checkOut: () => boolean
}
Ambos tienen diferencias minímas, asi que puedes usar uno u otro sin preocuparte demasiado. Aunque personalmente prefiero los Alias Types.
Lo que sí es que te recomiendo utilizar solo uno de los 2. Mas que nada para mantener tu código consistente y limpio.
Recuerda, al final del día el punto es que sea entendible y si usas ambos, tu equipo se preguntará si hubo alguna razón técnica para usar uno sobre otro.
Genéricos – (Generics)
Los genéricos permiten utilizar una misma función cambiando el tipo de dato de entrada y/o de salida. Esto permite reutilizar un mismo código para muchos casos.
const fetchApi = async <T>(path: string): Promise<T> => {
const response = await fetch(`https://example.com/api${path}`);
return response.json();
}
En este ejemplo estamos llamando a un API que nos va a devolver una lista de objetos. Al implementar genéricos, podemos determinar que tipo de objeto estamos manejando en la función al momento de llamarla, De esta manera podemos reutilizar el código de fetch y hacer peticiones a cualquier url que nosotros queramos sin preocuparnos por que tipo de dato nos pueda devolver el API.
Podemos simplemente específicar el tipo de dato que esperamos obtener de la petición al API:
fetchApi<Employee>('/employees');
fetchApi<Office>('/offices');
Y en caso de cometer algun error, Typescript nos indicará que el tipo de dato no es lo que se esperaba. Este ejemplo lanzará un error porque el tipo de dato que nos devuelva el api en /holidays, no concordará con lo que definimos en el dato de Office.
fetchApi<Office>('/holidays');
Enums
Los enums son un tipo de dato que permite representar valores constantes con un nombre legible. Cada constante puede tomar un valor numérico o de texto. Aunque le comportamiento por defecto es asignarles un valor numérico.
export enum ColorType {
RED,
BLUE,
GREEN,
PURPLE
}
En este caso cada elemento tiene un vlor asignado del 0 al 3.
Por otro lado si quieres especificar un valor específcico también puedes hacerlo:
export enum ColorType {
RED = 1,
BLUE = 2,
GREEN = 3,
PURPLE = 4
}
export enum ColorType {
RED = 'RED',
BLUE = 'BLUE',
GREEN = 'GREEN',
PURPLE = 'PURPLE'
}
Repitiendo sobre puntos anteriores. El punto de usar estas funcionalidades es proveer claridad.
Nada te detiene de usar simples consantes en lugar de un enum. Pero los enums proveen una forma de agrupar todas las constantes de un mismo tipo.
Por esto mismo, por lo general se usan para listar los multiples tipos de valores que puede tener un elemento. Siempre y cuando las opciones sean un número finito de elementos por supuesto.
Bonus – Clases
Como bonus no puedo omitir la mención de un concepto muy importante de la programación orientada a objetos (POO): las clases.
Una clase tiene el propósito de agrupar propiedades y funcionalidades que le corresponden a una entidad. Esto puede ser cualquier cosa que necesite ser representada en el sistema. Un usuario, un vehículo, un ticket, etc.
Si no estas familizarizado con el concepto de clases, te recomiendo que leas un poco acerca de POO. Ya que el concepto de “clase” es la parte básica del mismo.
La realidad es que si bien es un concepto importante, javascript siempre ha sido capaz de manejar el concepto por si mismo a través del uso de prototipos e incluso añadió la sintaxis de class desde la versión de EcmaScript 6.
Typescript porsupuesto también ofrece esta funcionalidad y aunque no es algo único del lenguaje es importante mencionarlo.
Al final el punto de usar Typescript es usar las funcionalidades de tipado y el punto de tener esas funcionalidades es hacer más claro el código. No solo para ti, sino para los demás.
Escribir buen código es un arte y todos tenemos que apuntar a crear código que se pueda entender con solo leerlo.