¡Hasta -30% en todos los libros en línea,
eformaciones y vídeos*! Código: NEURONA30 Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí

Tipos e instrucciones básicas

Variable y alcance

Para declarar una variable en TypeScript, existen tres palabras clave, cada una con un propósito muy distinto: var, let y const. Estos influirán en el alcance de la variable que declaren.

El alcance de una variable (también llamado scope o vida útil de la variable) corresponde a la porción de código en la que la variable existe y es accesible.

La palabra clave var está destinada a dejar de usarse, en favor de la pareja let/const. Por lo tanto, en el código TypeScript moderno, es poco probable encontrarla. Sin embargo, sigue siendo interesante entender cómo funciona.

Una variable declarada con la palabra clave var tiene un alcance equivalente al bloque de funciones en el que se definió.

Ejemplo:

function fn() {  
  var firstName = "Evelyn";  
  
  // Log: Evelyn  
  console.log(firstName);  
}  
  
// Compilation Error TS2304:  
// Cannot find name 'firstName'.  
console.log(firstName); 

En la última línea de este ejemplo, la variable firstName se usa fuera de la función en la que fue declarada. El compilador de TypeScript arroja un error que indica que esta variable no está definida. Si la variable no se declara dentro de una función, se trata de una variable global. Por lo tanto, es accesible desde cualquier...

Tipos básicos

1. Introducción

Como se explica en el capítulo Introducción, JavaScript es un lenguaje de tipado dinámico. Por tanto, los tipos se determinan durante la interpretación del código. Sin embargo, es posible encontrar estos tipos utilizando el operador typeof. TypeScript ofrece agregar el tipado estático, lo que permite determinar los tipos durante la fase de compilación.

En el resto de este trabajo, la denominación tipo JavaScript se referirá al tipo determinado por el intérprete. De lo contrario, se tratará de un tipo TypeScript.

2. Tipos primitivos básicos

TypeScript tiene los siguientes tipos primitivos: string, number, boolean, null, undefined, symbol y bigint. Para tipar una variable, debe especificar su tipo justo después de declararla.

Sintaxis:

let/const variable: type; 

Ejemplo:

const firstName: string = "Evelyn";  
const age: number = 34;  
const isCEO: boolean = false; 

Una vez tipada la variable, el entorno de desarrollo proporciona autocompletado y el compilador de TypeScript puede informar errores relacionados con el tipado.

Ejemplo (Visual Studio Code):

images/02RI01.png

A continuación se muestran algunos casos de errores clásicos informados por TypeScript dentro de Visual Studio Code:

  • Usar un método o propiedad que no pertenece a un tipo.

images/02RI02.png

El compilador de TypeScript genera un error en la última línea que indica que el método toExponential() no existe en el tipo string. Si este código se ejecutara en un navegador, provocaría un error indicando que firstName.toExponential() no es una función.

  • La asignación de un valor que tiene un tipo diferente al declarado a nivel de variable.

images/02RI03.png

Este código no produce un error si se ejecuta dentro de un navegador. El compilador de TypeScript evita asignar un valor de un tipo diferente al de la declaración de variable, para mantener la coherencia al escribir el código.

Es importante no confundir los tipos primitivos string, boolean y number con sus respectivos tipos de objeto contenedor de String, Boolean y Number. Los Wrapper Object (o en español: objetos envoltorio) permiten utilizar métodos y propiedades en variables de tipos primitivos. Aunque tienen métodos estáticos útiles, son utilizados principalmente por el intérprete. Nunca debe usar estos...

Desestructuración

La desestructuración apareció con el lanzamiento de ECMAScript 2015 (consulte el capítulo Introducción). Se puede utilizar con arreglos u objetos, y permite extraer todos o parte de estos elementos para ponerlos en variables separadas. 

Sintaxis (objeto):

let/const {variable, variable2} = { variable: 1, variable2: 2}; 

Ejemplo (objeto):

const person = {  
  firstName: "Evelyn",  
  lastName: "Miller",  
  age: 34  
};  
  
const { firstName, lastName, age } = person;  
 
// Log: Evelyn  
console.log(firstName);  
  
// Log: Miller  
console.log(lastName);  
  
// Log: 34  
console.log(age); 

Sintaxis (arreglo):

let/const [variable, variable2] = [1, 2]; 

Ejemplo (arreglo):

const [name1, name2] = ["Evelyn", "John", "Bryan"];  
  
// Log: Evelyn  
console.log(name1);  
  
// Log: John  
console.log(name2); 

La desestructuración de arreglos y objetos no tiene la misma sintaxis, pero sí el mismo propósito. Es posible asignar un valor predeterminado a las variables.

Ejemplo (objeto):

const { firstName, age = 34 } = { firstName: "Evelyn" };  
  ...

Enumeración

Las enumeraciones (también llamadas enum) permiten definir un grupo de valores constantes. Su objetivo principal es evitar el uso de cadenas de caracteres o números directamente en el código. Hablamos de cadenas o números mágicos cuando no tienen ningún significado. Dificultan la legibilidad y la comprensión del código.

Ejemplo:

function fnTreatStatus(status: number) {  
  if (status === 1) {  
    //...  
  } else if (status === 2) {  
    //...  
  }  
} 

En este ejemplo, es imposible entender a qué corresponden los números 1 y 2. Manejar este tipo de cadenas de caracteres (o números) directamente en el código sin usar constantes puede causar problemas, especialmente en el caso de la refactorización de código. En este tipo de casos es mejor utilizar una enumeración.

Para crear enumeraciones en TypeScript, se debe usar la palabra clave enum. Hay dos tipos de enumeración: enumeraciones numéricas y enumeraciones literales. 

Ejemplo (numérico):

enum Status {  
  InOffice,  
  Remote,  
  Off  
}  
  
function fnTreatStatus(status: Status) {  
  switch (status) {  
    case Status.InOffice:  
      // ...  
      break;  
    case Status.Remote:  
      // ...  
      break;  
    case Status.Off:  
      // ...  
      break;  
  }  
} 

Ejemplo (literal):

enum Rank {  
  Head = "Head",  
  ServicesDirector = "Services Director",  
  FinancialDirector = "Financial Director"  
}  
  
  
function fnPromote(rank: Rank) {  
  switch (rank) { 
    case Rank.Head:  
      //...

Condicional If...Else

En TypeScript, la sintaxis de if...else y switch es similar a la gran mayoría de lenguajes de programación. Sin embargo, hay una particularidad que influirá en la evaluación de las condiciones: los valores evaluados como falsos (llamados falsy) y los valores evaluados como verdaderos (llamados truthy).

Los siguientes valores, evaluados en una condición, siempre devolverán false:

  • false

  • 0 (cero)

  • ’ ’

  • " " (cadena vacía)

  • null

  • undefined

  • NaN

Los otros valores se evaluarán como true.

Ejemplo:

const employeeTruthy = {  
  firstName: "Evelyn",  
  age: 42,  
  isOff: true  
}  
  
const employeeFalsy = {  
  firstName: undefined,  
  age: 0,  
  isOff: false  
}  
  
if (employeeTruthy.firstName) { // true  
  // ...  
}  
  
if (employeeTruthy.age) { // true  
  // ...  
}  
  
if (employeeTruthy.isOff) { // true  
  // ...  
}  
  
if (employeeFalsy.firstName) { // false  
  // ...  
}  
  
if (employeeFalsy.age) { // false  
  //...

Optional chaining

Al crear un objeto, las propiedades no inicializadas no existen. Usar o llamar a un método en una propiedad indefinida genera un error durante la ejecución del programa. Si el tipo de la propiedad indica que potencialmente no está definida, el compilador de TypeScript arroja un error si se usa directamente sin verificación previa.

Ejemplo:

function fnDisplayPersonAge(person: {   
  firstName: string,   
  age?: number}  
) {  
  // Compilation Error TS18048: 'person.age' is possibly 'undefined' 
  const years = person.age.toString();  
  console.log(`${  
    person.firstName  
    } is ${  
      years ? years : ""  
    } years old`  
  )  
} 

Para comprobar que una propiedad está definida, es posible utilizar una condición if...else o un operador ternario.

Ejemplo:

function fnDisplayPersonAge(person: {  
  firstName: string,   
  age?: number}  
) {  
  const years = person.age ? person.age.toString() : undefined;  
  console.log(`${  
    person.firstName  ...

Operadores

Los operadores son esenciales en los lenguajes de programación. Son numerosos y permiten todo tipo de operaciones, desde aritméticas, hasta operaciones bit a bit, pasando por conversión de tipos.

En este capítulo, los operadores se presentarán en forma de tabla resumen. Algunos (como el operador de igualdad estricta) se presentarán con más detalle en la siguiente sección (Zoom en los operadores).

En esta sección no hay ninguna referencia a los tipos de TypeScript. Siempre que se menciona un tipo, es un tipo de JavaScript determinado durante la interpretación del código.

1. Operadores aritméticos

TypeScript le permite utilizar los operadores aritméticos clásicos existentes en la gran mayoría de los lenguajes de programación.

Tabla resumen de operadores aritméticos:

Operador

Descripción

+

Suma

-

Resta

*

Multiplicación

**

Exponenciación

/

Resta

%

Residuo (módulo)

2. Operadores unarios

Algunos operadores se pueden utilizar con dos operandos; hablamos de operadores binarios. Cuando se pueden utilizar con un único operando, se denominan operadores unarios.

images/02RI10.png

Tabla resumen de operadores unarios:

Operador

Descripción

+

Convierte el operando en number.

-

Convierte el operando en number y luego aplica una negación.

++

Incrementa el operando en 1.

--

Disminuye el operando en 1.

!

Convierte el operando a boolean y aplica una negación.

delete

Elimina una propiedad de un objeto o un elemento de una matriz.

typeof

Devuelve el tipo del operando en forma de cadena de caracteres.

void

Evalúa el siguiente operando como...

Zoom en los operadores

En esta sección no hay ninguna referencia a los tipos de TypeScript. Siempre que se menciona un tipo, es un tipo de JavaScript determinado durante la interpretación del código.

1. Operadores unarios + y -

Los operadores unarios + y - convierten una cadena de caracteres a su equivalente de tipo number. Por lo tanto, si la cadena es un número entero, seguirá siendo un número entero; lo mismo ocurre con un número de punto flotante.

Ejemplo:

// Log: 100.20  
console.log(+"100.20");  
  
// Log: -100.20  
console.log(-"100.20");  
  
// Log: 100  
console.log(parseInt("100.20")); 

En este ejemplo, la última línea utiliza el método global parseInt(), que convierte una cadena de caracteres en su equivalente entero.

2. Operador unario !

La doble negación !! es una notación que se usa a menudo en TypeScript. Este es un doble uso del operador unario !, que convierte el operando a boolean. La primera ! convierte el operando en un boolean y le aplica una negación (por lo tanto, los llamados valores falsy devuelven true y todos los demás devuelven false). El segundo ! aplica una negación al operando previamente convertido para volver a una situación más comprensible (los llamados valores falsy devuelven false y todos los demás devuelven true).

Ejemplo:

const employee = {  
  firstName: "Evelyn",  
  lastName: "Miller",  
  status: 0 
};  
  
const hasStatus = !!employee.status;  
  
// Log: false  
console.log(hasStatus); 

3. Operadores == y ===

Es esencial comprender la particularidad de las igualdades/desigualdades...

Bucles

En la gran mayoría de los lenguajes de programación, existen bucles que permiten repetir una secuencia de instrucciones. TypeScript ofrece el trío for, while y do...while. Tienen una sintaxis y funcionamiento similar al de otros lenguajes de programación. Es por eso por lo que no se describirán en esta sección, para dar prioridad a los bucles específicos de TypeScript.

1. Bucles for...in

En TypeScript, cada propiedad de un objeto está vinculada a un identificador (que en sí mismo es un objeto). Esto proporciona varios datos sobre una propiedad: ¿Es enumerable? ¿Es modificable? ¿Cuál es su valor?

Se dice que una propiedad es enumerable si su descriptor tiene la propiedad enumerable establecida en true.

Ejemplo (descriptor de propiedad):

const person = {};  
  
Object.defineProperty(person, "firstName", {  
  configurable: true,  
  enumerable: true,  
  writable: true,  
  value: "Evelyn"  
});  
// Log: Evelyn  
console.log(person.firstName); 

El bucle for...in permite iterar sobre las claves de las propiedades enumerables de un objeto.

Sintaxis:

for (let/const key in object) {  
// ...  
} 

Ejemplo:

const person = {};  
  
Object.defineProperty(person, "firstName"...

Symbol

El tipo Symbol es un nuevo tipo primitivo estandarizado por ECMAScript 2015. Le permite representar datos únicos e inmutables.

Sintaxis:

let/const variable = Symbol("optional description"); 

Ejemplo:

const mySymbol1 = Symbol();  
const mySymbol2 = Symbol();  
const mySymbol3 = Symbol(42);  
const mySymbol4 = Symbol("description");  
  
// Compilation Error TS2367: This condition will always return  
// 'false' since the types 'unique symbol' and 'unique symbol'  
// have no overlap  
console.log(mySymbol1 === mySymbol2);  
  
// Log: symbol  
console.log(typeof mySymbol1); 

En este ejemplo, TypeScript informa un error de compilación que impide comparar los dos símbolos. Al ser únicos, esta comparación siempre devolverá false en tiempo de ejecución.

Los símbolos se pueden utilizar como claves dentro de un objeto. Este es también su principal caso de uso. El hecho de que los símbolos sean únicos garantiza que las claves nunca entrarán en conflicto con otras claves del objeto (cadena o símbolo).

Ejemplo:

const employee = {  
  firstName: "Evelyn",  
  lastName: "Miller",  
  status: 0  
};  
  
const specialStatus = Symbol("status");  
  
employee[specialStatus] = 5;  
  
// Log: 5  
console.log(employee[specialStatus]);  ...

Iteración y colecciones

1. Iterador

Ciertas funcionalidades solo operan en los llamados «objetos iterables». Para que un objeto sea iterable, debe respetar el protocolo Iterator especificado por ECMAScript 2015. Le permite definir la forma de iterar sobre un objeto. Algunos objetos JavaScript lo implementan de forma nativa y, por lo tanto, se denominan objetos iterables (ejemplo: arreglo, cadena de caracteres, Map/Set...).

Para cumplir con el protocolo, un objeto iterable debe tener un método con clave [Symbol.iterator] que devuelva un objeto llamado iterador. El objeto iterador debe tener un método llamado next() que calculará cómo obtener el siguiente elemento de la secuencia. Este método debe devolver un objeto que contenga dos propiedades:

  • done: valor de tipo boolean que indica si quedan elementos en la secuencia.

  • value: valor de la última iteración.

Dado que no todos los objetos son iterables de forma nativa, es posible implementar el protocolo Iterator para que lo sean.

Ejemplo (for...of con iteración personalizada):

const iterableEmployees = {  
  [Symbol.iterator]() {  
    let counter = 0;  
    const iterator = {  
      next() {  
        counter++;  
        if (counter === 1) {  
          return { value: "Evelyn", done: false };  
        } else if (counter === 2) {  
          return { value: "Patrick", done: false };  ...

Funciones

Las funciones existen en la gran mayoría de los lenguajes de programación. En TypeScript, tienen una cierta cantidad de especificidades y su dominio se vuelve esencial para la programación funcional (consulte el capítulo TypeScript y la programación funcional).

1. Los conceptos básicos

Es posible declarar una función de dos maneras:

Sintaxis (estándar):

function functionName(param1: type, param2: type, ...): type {  
// ...  
}  
functionName (arg1, argN); 

Sintaxis (asignación en una variable):

const functionAlias = function functionName(  
  param1: type,  
  param2: type,  
  ...  
): type {  
// ...  
}  
functionAlias (arg1, argN); 

En la segunda sintaxis, la variable fnAlias obtendrá una referencia que apunta al área de memoria donde está declarada la función fn. Las funciones declaradas de esta manera tienen ventajas si se utilizan como parámetros de otras funciones (consulte el capítulo TypeScript y la programación funcional) o en el caso de las closures (cierres en español, consulte la sección Closures).

TypeScript no puede inferir el tipo de parámetros de función, por lo que es necesario especificarlos. Sin embargo, se puede inferir el tipo de retorno de las funciones.

Ejemplo (Visual Studio Code):

images/02RI11.png

Los parámetros de una función pueden tener un valor predeterminado.

Ejemplo:

function isEmployable(hasResume = false, age = 18) {  
  return hasResume && age >= 18;  
}  
  
isEmployable();  
isEmployable(true);   
isEmployable(true, 20); 

Al declarar un parámetro con un valor predeterminado, no es necesario especificar el tipo de parámetro. El compilador puede inferirlo.

Los parámetros de una función se pueden definir como opcionales agregando el carácter «?» después del nombre del parámetro.

Ejemplo:

function isEmployable(hasResume = false, age?: number) {  
  return hasResume && age && age >= 18;  
}  
  
isEmployable();  
isEmployable(true);  
isEmployable(true, 20); 

La única restricción...

Prototipo

En TypeScript, cada objeto tiene una propiedad que contiene un enlace a otro objeto denominado prototipo (llamado __proto__). Este mismo objeto prototipo contendrá un enlace a otro objeto prototipo y así sucesivamente; de ahí el nombre «cadena de prototipos».

images/02RI12.png

Estos objetos prototipo tienen propiedades y métodos que se comparten entre todos los objetos que hacen referencia a ellos como prototipos (a través de su cadena de prototipos). Por tanto, cada objeto tiene métodos/propiedades propios y métodos/propiedades pertenecientes a los objetos prototipo que forman parte de su cadena. Cuando el intérprete de JavaScript intenta resolver una llamada a una propiedad, primero busca en las propiedades específicas del objeto y luego avanza en la cadena del prototipo hasta encontrar la propiedad.

Cada objeto hace referencia, al menos, a un prototipo en su cadena: Object.prototype. Este contiene métodos y propiedades específicas de los objetos. Por eso se dice habitualmente que en TypeScript todo es un objeto. Las matrices, los objetos literales, las funciones, pero también los tipos primitivos (que pueden envolverse con su respectivo contenedor de objetos) hacen referencia al prototipo de los objetos en su cadena.

Las clases estandarizadas por ECMAScript 2015 son solo azúcares sintácticos destinados a hacer más intuitiva la programación orientada a objetos...

Gestión de excepciones

En TypeScript, existe el bloque try/catch/finally, que permite manejar las excepciones que ocurren durante la ejecución del programa.

Sintaxis:

try {  
  //...  
} catch (e) {  
  //...  
} finally {  
  //...  
} 

Ejemplo:

try {  
  openSqlConnection()  
} catch (e) {  
  console.log(‘Error while trying to open SQL connection', e);  
} finally {  
  closeSqlConnection();  
} 

El bloque try/catch solo funciona en tiempo de ejecución. Por lo tanto, si la sintaxis del bloque no es válida, no funcionará.

Es posible activar excepciones utilizando la palabra clave throw.

Sintaxis:

throw new Error("message"); 

Ejemplo:

setEmployeeName(firstName: string) {  
  if(typeof firstName !== ‘string' {  
    throw new Error(‘invalid parameter'); 
 
  }  
} 

La instancia de la clase Error guarda toda la información que permite localizar el origen de la excepción.

El concepto de clase se abordará en el capítulo Programación orientada a objetos.

Sin embargo, es posible generar una excepción sin crear una nueva instancia de la clase...