Typescript tutorial rápido

5 minutos

Typescript

Trabajar con Javascript implica una gran cantidad de ventajas, como la facilidad a la hora de desarrollar por su plasticidad o su ecosistema presente en casi cualquier ámbito. Pero, a pesar de su popularidad, cuando uno empieza a crear Web Apps cada vez más complejas encuentra duras limitaciones. Por ello Microsoft decidió encargarle a Anders Hejlsberg (diseñador de C#, Microsoft.NET, creador de Turbo Pascal, Delphi..) realizar una capa que añadiera seguridad y estabilidad a Javascript. Después de casi 2 años de trabajo acabó apareciendo en 2014 la versión estable de Typescript, un superconjunto que otorga tipos estáticos, objetos reales, eliminación de variables nulas y compatibilidad con navegadores antiguos.

En la siguiente tutorial vamos a ver ejemplos prácticos para aprender, o para otros repasar, sus partes más importantes.

Instalación

Los archivos de Typescript deben tener la extensión .ts. Por otro lado esos archivos se deberán compilar, o preprocesar, para transformarlos en Javascript. Recordemos que el navegador no sabe que es Typescript.

Instalamos su compilador.

npm install -g typescript

Creamos un archivo de ejemplo con el nombre elton-john.ts y el siguiente contenido.

function reproducir(cancion) {
    alert('Estamos escuchando ' + cancion)
}

reproducir('Rocket Man')

Ahora compilamos nuestro código Typescript.

tsc elton-john.ts

Creará el archivo elton-john.js perfectamente listo para ejecutarse con cualquier navegador.

Existen otras herramientas más completas para esta labor como parcel o prepros, no dudes en investigar al respecto.

Variables

Son similares a Javascript.

// Local
let planeta = 'Tierra'
// Constante
const gravedad = 9.8
// Global
var enGalaxia = true

Pero deben ser tipadas.

// Texto
let planeta: string = 'Tierra'
// Número, tanto entero como con decimal (float)
const gravedad: number = 9.8
// Booleano
var enGalaxia: boolean = true
// Cualquiera
let especie: any = 'Humanos'

En el caso de necesitar seleccionar un Elemento.

let formulario: HTMLFormElement = document.querySelector('#formulario')
let ul: HTMLUListElement = document.querySelector('#errores')
let input: HTMLInputElement = document.querySelector('#nombre')
let boton: HTMLButtonElement = document.querySelector('#guardar')
...

Array y Tuplas

Cuando declaremos una lista hay que definir los tipos de su contenido.

// Array de que contiene textos
let planetas: string[] = ['Mercurio', 'Venus', 'Tierra', 'Marte']
// Array de que contiene números
let masas: number[] = [3, 1, 5.3, 0.5, 2]
// Array con booleanos
let rocosos: boolean[] = [true, false, false, true]
// Array que contiene cualquier elemento
let perdidos: any[] = [9, true, 'asteroides']
// Tupla, los elementos son limitados y de tipos fijos
let diametro: [string, number] = ['Saturno', 116460]

Enum

En algunas ocasiones debemos trabajar con listas de números, cuyo significado es opaco por el origen de los datos, por suerte Typescript nos facilita la tarea. Una manera de utilizar listas de números de una forma más amigable es con el tipo Enum.

En el siguiente ejemplo se quiere disponer de los números 0, 1 y 2.

// Creo la enumeración y llamo al tipo Estado
enum Estado {Solido, Liquido, Gaseoso}

// Guardo un Estado en una variable
let jupiter: Estado = Estado.Gaseoso;

console.log(jupiter)
// 2

Si no marco lo contrario siempre empezará por 0. En caso de querer especificar el inicio de Enum lo indico al principio.

// Creo la enumeración desde 30
enum Estado {Solido = 30, Liquido, Gaseoso}

let jupiter: Estado = Estado.Gaseoso;

console.log(jupiter)
// 32

En caso de querer personalizar cada elemento se lo dicto.

enum Estado {Solido = 10, Liquido = 5, Gaseoso = 8}

let jupiter: Estado = Estado.Gaseoso;

console.log(jupiter)
// 8

Funciones

Simple

En el siguiente ejemplo apreciamos una funcion que no requiere argumentos de entrada ni de salida. Se le añade void (vacio) para señalar que no dispone de un retorno.

function rotarPlaneta(): void {
    console.log('Girando...')
}

rotarPlaneta()
// Por consola: "Girando..."

Argumentos de entrada

Aquí indicamos un argumentos de entrada.

function rotarPlaneta(grados: number): void {
    console.log(`Girando ${grados}...`)
}

rotarPlaneta(45)
// Por consola: "Girando 45..."

Si queremos incluir varios no hay problema.

function rotarPlaneta(grados: number, planeta: string): void {
    console.log(`Girando ${planeta} unos ${grados}...`)
}

rotarPlaneta(45, 'Marte')
// Por consola: "Girando Marte unos 45..."

Aunque algunos también puede ser opcionales, para ello termina con un interrogante los nombres de las variables: grados?. En caso de no ser definida su valor será undefined.

function rotarPlaneta(grados?: number): void {
    if (grados === undefined) {
        console.log('No giramos')
    } else { 
        console.log(`Girando ${grados}...`)
    }
}

rotarPlaneta()
// Por consola: "No giramos"
rotarPlaneta(45)
// Por consola: "Girando 45..."

Otra posibilidad es dando un valor a la variable en caso que no fuera definida.

function rotarPlaneta(grados: number = 360): void {
    console.log(`Girando ${grados}...`)
}

rotarPlaneta()
// Por consola: "Girando 360"
rotarPlaneta(45)
// Por consola: "Girando 45..."

Retorno

Cuando las funciones devuelvan un valor colocaremos un return en su interior y adicionalmente el tipo después de los dos puntos.

function zonaHabitable(radio: number): number {
    return Math.round(Math.PI * Math.pow(radio, 2))
}

zonaHabitable(23)
// 1662
function zonaHabitable(radio: number): string {
    return `Puede ser colonizado ${Math.round(Math.PI * Math.pow(radio, 2))} metros`
}

zonaHabitable(23)
// Puede ser colonizado 1662 metros

Interfaces

Cuando en una función queremos introducir o devolver un elemento más complejo que una sola variable hay que recurrir a las Interfaces. También denominados “Tipificación de pato” (si 🦆) o “subtipo estructural”.

Por ejemplo, deseo introducir por separado el nombre y el radio, pero quiero en la salida en un objeto (JSON) con sus claves definidas.

function zonaHabitable(name: string, radio: number): {name: string, radio: number} {
    return {
        name: name.toUpperCase(),
        radio: Math.round(Math.PI * Math.pow(radio, 2))
    }
}

zonaHabitable('Plutón', 57)
// { name: 'PLUTÓN', radio: 10207 }
zonaHabitable('Plutón', 57).radio
// 10207

Para reutilizarlas podemos aislarlas con la estructura de interface.

interface DatosPlaneta {
    name: string,
    radio: number
}

function zonaHabitable(name: string, radio: number): DatosPlaneta {
    return {
        name: name.toUpperCase(),
        radio: Math.round(Math.PI * Math.pow(radio, 2))
    }
}

zonaHabitable('Plutón', 57)
// { name: 'PLUTÓN', radio: 10207 }

Además lo podemos integrar como parámetro de entrada.

interface DatosPlaneta {
    name: string,
    radio: number
}

function zonaHabitable(datos: DatosPlaneta): string {
    return `${datos.name } puede ser colonizado ${Math.round(Math.PI * Math.pow(datos.radio, 2))} metros`
}

zonaHabitable({name: 'Jupiter', radio: 97})
// Jupiter puede ser colonizado 29559 metros

En el caso de que algunos campos no sean obligatorios definirlos marcaremos un interrogante después del nombre. Observa numeroLunas.

interface DatosPlaneta {
    name: string,
    radio: number,
    numeroLunas?: number
}

function zonaHabitable(datos: DatosPlaneta): string {
    let textoFormateado = `${datos.name } puede ser colonizado ${Math.round(Math.PI * Math.pow(datos.radio, 2))} metros`
    // En caso de que datos.numeroLunas no sea undefined
    if (datos.numeroLunas) {
        // Concadenamos el número de lunas
        textoFormateado += ` y alguna de sus ${datos.numeroLunas} lunas`
    }
    return textoFormateado
}

zonaHabitable({name: 'Jupiter', radio: 97})
// Jupiter puede ser colonizado 29559 metros
zonaHabitable({name: 'Jupiter', radio: 97, numeroLunas: 79})
// Jupiter puede ser colonizado 29559 metros y alguna de sus 79 lunas

Importar

Para importar librerías externas Typescript nos lo hace muy fácil.

En el caso que necesitemos, por ejemplo, Axios (simplifica las peticiones AJAX) seguiremos los siguientes pasos.

Instalamos Axios con npm.

npm i axios

Y ahora lo importamos para a continuación utilizarlo.

// Importamos
import axios from 'axios'

// Ejecutamos

axios.get('https://jsonplaceholder.typicode.com/todos/1')
  .then(function (response) {
    console.log(response.data);
  })
  
// { userId: 1, id: 1, title: 'delectus aut autem', completed: false }

O JQuery.

npm i jquery
import $ from 'jquery'

$.trim('  agujero negro ')
// 'agujero negro'

Clases y Objetos

Cuando queramos crear una clase y declarar un objeto utilizaremos la siguiente estructura.

// Declaramos la clase
class Satelite {
    constructor() {
        console.log('Satelite creado')
    }
}

// Instanciamos el objeto
new Satelite()
// Por consola: Satelite creado

Para añadir parámetros lo declaramos fuera del constructor.

class Satelite {

    // Variables
    velocidad: number

    constructor(velocidad: number) {
        // Usa this para referenciar las variables del objeto
        this.velocidad = velocidad
    }
}

let miSatelite: Satelite = new Satelite(82)

console.log(miSatelite.velocidad)
// Por consola: Satelite creado

La visibilidad es importante, marcamos que será accesible fuera (public) y que solo podrá usarse dentro (private).

class Satelite {

    public velocidad: number
    private activo: boolean

    constructor(velocidad: number) {
        this.velocidad = velocidad
        this.activo = false
    }
}

let miSatelite: Satelite = new Satelite(82)
console.log(miSatelite.velocidad)
// 82
console.log(miSatelite.activo)
// ERROR

Las funciones son declaradas sin utilizar la palabra function.

class Satelite {

    public velocidad: number
    private activo: boolean

    public constructor(velocidad: number, activo: boolean) {
        this.velocidad = velocidad
        this.activo = activo
    }

    public estado(): void {
       console.log(`El satelite esta ${this.activo ? 'activo' : 'apagado'} y se mueve a ${this.velocidad} Km/h`) 
    }
}

let miSatelite: Satelite = new Satelite(32, false)
miSatelite.estado()
// El satelite esta apagado y se mueve a 32 Km/h
let miSegundoSatelite: Satelite = new Satelite(11, true)
miSegundoSatelite.estado()
// El satelite esta activo y se mueve a 11 Km/h

Tal vez también te interese...