Try   HackMD

Typescript (TS)

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Introducción

¿Qué es Typescript?

TypeScript (ts) es un lenguaje de programación libre y de código abierto desarrollado y mantenido por Microsoft. Es un superconjunto de Javascript, que esencialmente añade tipos estáticos y objetos basados en clases.

¿Para qué sirve Typescript?

Typescript trata de resolver todos los posibles errores de Javascript en el momento en el que se escribe el código Javascript al proporcionar un tipado estático y encapsulación para generar un código libre de problemas.

Typescript en realidad es un compilador de Javascript que convierte el código Typescript a Javascript con la certeza de que el código funcionará de la forma correcta. Con Typescript es posible identificar errores en el momento en el que se esta escribiendo el código, antes de compilar el código o realizar pruebas.

Ventajas de Typescript

​​​​1. Lenguaje tipado
​​​​2. Opciones adicionales de JS

1. Lenguaje tipado

A diferencia de Javascript que es un lenguaje débilmente tipado, Typescript es un lenguaje con tipado estático, es decir, es necesario incluir el tipo de datos en variables, funciones, parámetros, entre otros. El objetivo principal de Typescript es identificar errores relacionados con el tipo de datos señalarlos antes de la compilación para que dichos errores sean solucionados.

2. Opciones adicionales de JS

Typescript además de proporcionar tipos de datos, provee de otras carácteristicas adicionales como diversas estructuras de datos, interfaces y elementos avanzados relacionados con el DOM.

Tipos de datos

Al igual que Javascript en Typescript existen diferentes tipos de datos como:

  • Números (numbers)
  • Cadenas (strings)
  • Booleans
  • Objetos (objetcs)
  • Arreglos (arrays)

Los tipos de datos anteriores los hemos visto anteriormente en la guía de Javascript (JS).

En Typescript para asignar el tipo de dato en la declaración se hace de la siguiente forma:

let age: number;
let name: string;
let canVote: boolean;

En el caso del arreglo, se específica el tipo de dato de los elementos del arreglo:

let nums: number[];
let names: string[];

Aunque si en la declaración de la variable se realiza la asignación, no es necesario incluir el tipo de dato.

Asimismo, Typescript añade otros tipos de datos como:

  • Tuplas (Tupple)
  • Enumeración (Enum)
  • Alguno (Any)
  • Desconocido (Unknown)

Abordaremos estos tipos de datos a detalle:

Tuplas (Tupple)

Las tuplas (tupple) son una secuencia de valores agrupados como si se tratarán de un único valor. Una vez que se declara una tupla (tupple) no puede ser modificada. Ejemplo:

let myTupple: Tupple;
myTupple = [3, 'Apples'];

Como podrás notar una tupla es similar a un arreglo, por lo que, para acceder a las propiedades de una tupla, podemos hacerlo mediante el índice:

console.log(myTupple[1]); //output "Apples"

Enumeración (Enum)

El tipo de dato enum se utiliza para otorgar un valor númerico y con ese número identificar un valor en específico, es algo similar a otorgar un índice.
Ejemplo:

enum Role {
    READ_ONLY,
    CLIENT,
    ADMIN
}

let user = {
    name: "John",
    lastname: "Doe",
    role: Role.ADMIN
}

console.log(user.role); //output 2;

Alguno (any)

Typescript contiene un comodín cuando no se especifica el tipo de dato o cuando el tipo de dato no es relevante. Para ello, hace uso del tipo de dato any:

let randomVariable: any;

Nota: En typescript cuando en una variable no se específica el tipo de dato, por defecto Typescript le otorga any.

En el caso de un arreglo con elementos de tipo de datos distintos, podemos declararlo como tipo de dato any:
let mixedArray: any[];

Desconocido (unknown)

Por otro lado, existe el tipo de dato unknown que es básicamente el mismo que any con la diferencia de que con any puedes puedes asignar un valor any a una variable number, string o boolean. Pero con unknown no puedes asignar un valor unknown a una variable number, string o boolean. Ejemplo:

✅ let someVar: any;
✅ let someNumber: number;
✅ someVar = 5;
✅ someNumber = someVar;

✅ let someVar2: unknown;
✅ let someNumber2: number;
✅ someVar2 = 5;
❌ someNumber2 = someVar2;

Casting

Funciones con tipo de dato en el parámetro

En Javascript los parámetros de las funciones pueden ser de cualquier tipo de dato, pero no es lo mejor debido a que en ocasiones los usuarios no pueden pasar los valores correctos en los parámetros. Por ejemplo, analicemos la siguiente función de suma:

function sum(num1, num2) {
    const res = num1 + num2;
    return res;
}

En la función anterior estamos esperando dos valores de tipo number, como por ejemplo sum(5,3), con este ejemplo el resultado de llamar a la función sería 8. Pero, qué pasaría si en lugar de numbers le pasamos a la función strings como parámetros, por ejemplo sum("5", 3), el resultado de la llamada a la función en el ejemplo anterior sería 53, claramente ese no es el resultado que esperamos. Con javascript podríamos solucionar ese problema con lo siguiente:

function sum(num1, num2) {
    if(typeof num1 === 'number' && typeof num2 === 'number') {
        return num1 + num2;
    } else {
        return parseFloat(num1) + parseFloat(num2);
    }
}

Pero con typescript podemos solucionarlo de una forma más sencilla, al proporcionar el tipo de dato en los parámetros de la función:

function sum(num1: number, num2: number) {
    return num1 + num2;
}

En el ejemplo anterior, se le asigna el tipo de dato number a los parámetros num1 y num2. Por lo que, si se intenta llamar a la función con un parámetro que no sea number, typescript no permitirá llamar a la función y arrojará un error.
❌ sum("5", 3);

Union Types

Typescript permite que en los parámetros se pueda definir más de un tipo de dato. Tomemos el ejemplo anterior, si quisieramos diseñar una función para concatenar dos números (number) o dos cadenas (string), con el código anterior al pasar dos cadenas como parámetro typescript nos regresaría un error. Para permitir que la función sum pueda concatenar tanto strings como numbers podemos hacer uso de los union types, con los cuales le diremos a typescript que puede recibir tanto un string o un number, aquí un ejemplo:

function sum(param1: number | string, param2: number | string) {
    return param1 + param 2;
}

Con lo anterior podríamos mandar a llamar a la función sum de la siguiente manera:

const myNumber = sum(5+3);
const myString = sum("Hello ", "World");
console.log(myNumber); //output 8
console.log(myString); //output "Hello World"

Literal Types

Por otra parte, typescript además de permitir en los parámetros dos tipos de valores, también permite ser más especifico al poder determinar valores especificos en los parámetros. Por ejemplo:

function convertGradesTo(grades: number, currentUnit: 'c' | 'f') {
    let res;
    let changeTo;
    if(currentUnit === 'c') {
        res = grades * (9/5);
        changeTo = 'Fahrenheit';
    } else {
        res = (grades - 32) * (5/9);
        changeTo = 'Celcius';
    }

    return `The temperature in ${changeTo} is: ${res}º`;
}

let conversion = convertGradesTo(23, 'f');
console.log(conversion); //output "The temperature in Celcius is: -5º"

Como podemos observar en el ejemplo anterior, el parámetro currentUnit podría ser c o f, pero no aceptaría un valor diferente al declarado en el parámetro.
❌ convertGradesTo(23, 'k');

Type Aliases

Asimismo, typescript permite crear tipos de datos basados en los literal types con la finalidad de hacer el código más limpio o implementar estos tipos de datos específicos en diferentes archivos ts. Para declarar un type alias se debe hacer uso de la palabra reservada type aquí un ejemplo:

type Combinable = number | string;

function potential(base: Combinable, exp: Combinable) {
    const res = (+base) ** (+exp);
    return res;
}

const myPot = potential(5,'3');
console.log(myPot); //output 125

En el ejemplo anterior, creamos un tipo de dato nuevo llamado Combinable que puede ser number o string.

Return Types

Por otra parte, es posible asignar un tipo de dato al valor de retorno de la función, algo similar a lo que sucede con los parámetros de la función. Retomemos, el ejemplo de la suma de los numbers, para determinar que la función se realice correctamente y se retorne un número, delante de los parámetros colocaremos el tipo de dato que debe regresar la función. Ejemplo:

function sum(n1: number, n2: number): number {
    return n1 + n2;
}

Vacio (void)

En caso de que no se retorne ningún valor en la función, indicaremos el tipo de dato void.
Ejemplo:

function showAlert(message: string): void {
    window.alert(message);
}

Interfaces (interface)

Una interfaz es un conjunto propiedades y métodos cuya funcionalidad es la de determinar el funcionamiento de una clase, es decir, funciona como un molde o como una plantilla.
Una interfaz se debe declarar con la palabra reservada interface delante de la palabra reservada debe colocarse el nombre de la interfaz, por convención debe nombrarse con Camel Case. Las propiedades y métodos deben encerrarse entre llaves {} y en el caso de las propiedades debe especificarse los tipos de datos. A continuación un ejemplo:

interface User {
    name: string;
    lastname: string;
    email: string;
    age: number;
    married: boolean;
}

La interfaz anterior se puede usar como tipo de dato de una variable:

let person: User;
person = {
    name: "John",
    lastname: "Doe",
    email: "john.doe@mail.com",
    age: 30,
    married: false
}

En caso de que algún dato definido en la interfaz no sea proporcionado en la asignación de la variable de tipo User, typescript arrojará un error. Por ejemplo:

let person2: User;
person2 = {
    name: "Mark",
    lastname: "Richards",
    age: 41,
    married: true
}

En el ejemplo anterior, typescript arrojaría un error al momento de compilar el código a javascript ya que la propiedad email no fue asignada en person2.

Clases

Al igual que en Javascript, en Typescript es posible implementar una clase. Para ello, al igual que en Javascript haremos uso de la palabra reservada class. Con typescript podremos determinar el tipo de dato de las propiedades de la clase, así como el tipo de retorno en los métodos. Ejemplo:

class ShopCart {
    total: number;
    items: string[];
    startDate: string;
    numberItems: number;
    
    constructor() {
        this.startDate = new Date();
    }
    
    obtainTotal(): number {
        return this.items.reduce((total: number, sum; number)) => total + sum;
    }
}

Nota: En el caso de las clases (class) y las interfaces (interface) es posible declarar una propiedad como opcional, esto se hace con la ayuda del símbolo ? y se coloca delante del nombre de la propiedad opcional, pero antes de :. Ejemplo:

interface User {
    name: string;
    lastname: string;
    email: string;
    age?: number;
    married?: boolean;
}

En el ejemplo anterior, las propiedades age y married son opcionales, por lo que, si se crea una instancia de la interfaz sin esos valores, typescript lo permitiría sin arrojar ningún error.

let person: User;
person = {
  name: "John",
  lastname: "Doe",
  email: "john.doe@mail.com"
}

Compilar archivos typescript(.ts)

Como mencionamos al principio de esta wiki, typescript es solo un lenguaje de programación que se encargará de compilar el código y al final entregará un archivo de javascript. Para ello, debemos descargar el compilador para posteriormente utilizar el comando tsc. Para obtener la funcionalidad del comando de ts compiler debemos instalar mediante npm:
npm install -g typescript
Una vez que tengamos instalado typescript, podemos compilar nuestro código mediante el comando:
tsc <nombreDelArchivo.ts>
Al ejecutar el comando anterior, obtendremos un archivo js con el mismo nombre del archivo.