Introducción a ES6 y TypeScript (Microsoft)
December 30, 2020 · View on GitHub
Typescript es un lenguaje de programación que añade tipos a javascript. Suele describirse como un superset de javascript ya que todo código válido javascript es también un código válido typescript.
Se distribuye con una licencia abierta (Apache Licences 2.0) y es desarrollado y mantenido por Microsoft.
Se compila para generar código ES6 (también llamado ES2015) o ES5 (diciembre 2009).
Versiones de JavaScript: https://www.w3schools.com/js/js_versions.asp

Características de ES2015/ES6
Template literals
var texto: "Superman";
var template = `
<div>El héroe se llama ${texto} </div>
<button>Click me!</button>
<div>Esto es una capa</div>
<input type="text" value="nombre" />
`
- Multilínea
- Interpolación con sintaxis ${variable}
http://notasjs.blogspot.com/2013/04/strings-multi-linea-en-javascript.html
let/const
- Alternativas a var para declarar variables
- Scope restringido al bloque
for (var i = 0; i < 10; i++) {
// algo
}
console.log(i) // 10!
for (let j = 0; j < 10; j++) {
// algo
}
console.log(j) // j is not defined
-
No podemos usar una variable antes de definirla
-
Binding en cada iteración, nos permite crear funciones en bucles que utilicen variables dentro del for.
Arrow functions
- Funciones expresadas de forma compactas
increment = function(x) {
return x+1
};
increment = x => x+1;
- Con retorno implícito si sólo tienen 1 expresión (no hace falta el return ni las llaves)
- No hacen falta los paréntesis en los parámetros si sólo tienen 1 (si no, () => 1 o (a,b)=>a+b )
- No bindean this, por lo que es más fácil definir event handlers en el DOM.
for … of
- Iteración mejorada (no recorre propiedades padre como for ... in)
- Funciona con todos los iterables (como strings)
let iterable = [10, 20, 30];
for (let value of iterable) {
console.log(value);
}
// 10
// 20
// 30
Más ejemplos en: https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Sentencias/for...of
Sintaxis corta de objetos
Forma breve de definir objetos que usar como nombre de la variable el nombre de la propiedad.
let nombre = 'Carlos';
var apellido = "Herrera";
obj = {nombre: nombre, apellido: apellido} // antigua forma
obj = {nombre, apellido} // nueva forma
obj = {nombre, apellido, edad, sexo: sex} // nueva forma
Rest y spread
Operadores (¡diferentes!) con la misma sintaxis: … (3 puntos seguidos)
Spread sirve para extraer valores de un array o un objeto:
data = [1, 2, 3];
log(data[0], data[1], data[2]);
function log(a, b, c) {
console.log(`first value is ${a}, second is ${b} and third ${c}`)
};
data = [1, 2, 3];
log(... data); // uso de spread operator
function log(a, b, c) {
console.log(`first value is ${a}, second is ${b} and third ${c}`)
};
Rest para la operación inversa, de elementos a array:
log(1, 2, 3); // uso de rest operator
function log(... array) {
console.log(array) // array [1, 2, 3]
};
Valores por defecto
En parámetros de una función
function ejemplo(valor = 1) {
}
Destructuring
Descomponer arrays y objetos a variables
let arr = [0, 1, 2];
//Antes
//let a = arr[0];
//let b = arr[1];
//let c = arr[2];
//Ahora
let [a, b, c] = arr;
console.log(a, b, c) // 0, 1, 2
Se puede combinar con valores por defecto y operador rest.
let arr = [0, 1, 2];
let [a, ...b] = arr;
console.log(a, b) // 0, [1, 2]
let [a, b, c, d = 3] = arr;
console.log(a, b, c, d) // 0, 1, 2, 3
También podemos usarlo para invertir variables
let a = 0;
let b = 1;
[b, a] = [a, b];
console.log(a, b) // 1, 0
O para transformar parámetros de entrada de funciones
let arr = [0, 1];
log(arr);
function log([a, b]) {
console.log(a, b)
}
Clases
Soporte de:
- Herencia ( extends )
- Constructores ( constructor() {} )
- Métodos de instancia ( metodo() {} )
- Métodos estáticos ( static metodo() {} )
- Overrides de métodos a hijos ( super.metodo() )
- Llamadas a constructores padre ( super() )
class MyClass {
atributo;
metodo() {
}
constructor() {
}
}
Accessors get y set
class MyClass {
_atributo;
get atributo() {
return this._atributo;
}
set atributo(value) {
this._atributo = value;
}
}
let myObject = new MyClass();
myObject.atributo = 27;
console.log(myObject.atributo);
Módulos
Podemos crear ficheros javascript en los que exportemos clases,
funciones, variables o constantes con el keyword export:
Archivo miModulo.js
export function diHola(){
return "hola"
}
export let pi = 3.14
A los archivos que exportan cosas se les denomina módulos.
Después podemos importar dichos módulos desde otros archivos para usar sus elementos exportados:
import { pi, diHola } from './miModulo.js'
Más características de ES2015/ES6
- Soporte para Maps & Sets
- Soporte nativo de promesas
- Async/await
function resolveAfterTime(t){
let promesa = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("¡Promesa resuelta!");
}, t)
})
return promesa;
}
async function asincrona(){
console.log('calling');
var result = await resolveAfterTime(1000);
console.log(result);
console.log("fin");
}
Con async le decimos a JavaScript que trate nuestra función de forma diferente: cuando encuentre un await, se detendrá y esperará a la resolución de la operación asícrona antes de continuar con el resto del código.
Características de ES2016/ES7
Array.prototype.includes
Devuelve true si el array contiene el elemento indicado.
const arr = [1, 2, 3, 4, Nan];
//Antes
if(arr.indexOf(3) >= 0) {
...
}
//Con includes
if(arr.includes(3)) {
...
}
Includes también funciona para NaN, mientras que indexOf no.
arr.includes(NaN); //true
arr.indexOf(NaN); //-1
Exponentiation infix operator
//Antes
Math.pow(7, 2); //49
//Ahora
7**2; //49
Características de ES2017/ES8
Object.values()
Devuelve todos los valores de las propiedades del objeto, excluyendo las encadenadas mediante prototype.
const cars = { BMW: 3, Tesla: 2, Toyota: 1};
//Antes
const vals = Object.keys(cars).map(key => cars[key]);
console.log(vals); // [3, 2, 1]
//Ahora
const vals = Object.values(cars);
console.log(vals); // [3, 2, 1]
Object.entries()
Devuelve en forma de arrray las keys y los values
const cars = { BMW: 3, Tesla: 2, Toyota: 1};
//Antes
Object.keys(cars).forEach(function(key) {
console.log('key: ' + key + ' value: ' + cars[key]);
});
//Ahora
for(let[key, value] of Object.entries(cars)) {
console.log(`key: ${key} value: ${value}`);
}
const cars = { BMW: 3, Tesla: 2, Toyota: 1};
//Antes
const map1 = new Map();
Object.keys(cars).forEach(function(key) {
map1.set(key, cars[key]);
});
console.log(map1); // Map { BMW: 3, Tesla: 2, Toyota: 1}
//Ahora
const map = new Map(Object.entries(cars));
console.log(map1); // Map { BMW: 3, Tesla: 2, Toyota: 1}
String padding
Dos nuevos métodos en el objeto String para rellenar cadenas de texto.
- padStart
- padEnd
// 'someString'.padStart(numberOfCharcters [,stringForPadding]);
'5'.padStart(10) // ' 5'
'5'.padStart(10, '=*') //'=*=*=*=*=5'
'5'.padEnd(10) // '5 '
'5'.padEnd(10, '=*') //'5=*=*=*=*='
Características de ES2018
Mejoras en operador rest
Utilización de rest para extraer solamente una parte de las propiedades
let { firstName, age, ...remaining } = {
firstName: 'john',
lastName: 'smith',
age: 20,
height: '5.10',
race: 'martian',
};
firstName; // john
age; // 20
remaining; // { lastName: 'smith', height: '5.10', race: 'martian' }
Mejoras en operador spread
const person = { firstName: 'john', age: 20 };
const account = { EAN: 'xxx-5455-9246', amount: 500 };
const personAndAccount = { ...person, ...account };
personAndAccount; // { firstName: 'john', age: 20, EAN: 'xxx-5455-9246', amount: 500 }
Promise.prototype.finally()
Se incorpora el método finally() en las promesas. EL método finally se ejecutará siempre. No recibe ningún parámetro.
let started = true;
let myPromise = new Promise(function(resolve, reject) {
resolve('Promesa resuelta');
})
.then( val => console.log(val) )
.catch( error => console.log(error) )
.finally( () => started = false )
for-await-of Asynchronous Iteration
Permite crear bucles de códigos asíncronos.
const promises = [
new Promise(resolve => resolve(1)),
new Promise(resolve => resolve(2)),
new Promise(resolve => resolve(3)),
];
async function test() {
for await (const obj of promises) {
console.log(obj);
}
}
test(); //prints: 1 2 3
Características de TypeScript
- No es ejecutable. Debe ser compilado primero a ES5 o a ES6.
- Tiene las mismas características que ES5 + ES6 y aporta otras nuevas.
- Tiene detección de fallos al compilar.
Instalación
# npm install -g typescript
Compilación (transpilación)
# tsc index.ts
Se crea un archivo index.js que ya se puede ejecutar en un entorno javascript (navegador o node).
La compilación se puede afinar mediante modificadores para tener en cuenta muchas opciones.
Probablemente dos de las más prácticas son --lib y --target. La primera
indica las librerías de javascript que se deben usar para realizar la compilación,
mientras que la segunda indica qué versión de javascript deseamos utilizar en la
generación del código javascript.
Si por ejemplo queremos usar características de ES2018 (la última versión de Ecmascript) y crear archivos de javascript ES5 (la versión más soportada en los navegadores actuales), la compilación se llevaría a cabo así;
# tsc --lib ES2018 --target ES5 index.ts
Tipos
boolean | number | string | arrays | enum (enumerados) | Any (cualquiera) | Void (ninguno) | Object
let cadena: string;
cadena = 'Hola';
cadena = 2; // ERROR!
Con tipado gradual. Podemos no escribir un tipo y el compilador intentará inferirlo y hacer comprobaciones en tiempo compilación.
Tipo any para saltarse las comprobaciones de tipos.
La sintaxis en arrays es
let array1: Array<number>;
let array2: number[];
Interfaces
No generan código en producción, sólo son comprobaciones en tiempo de ejecución
interface Talk {
name: String;
}
let charla = {name: 'Rx'}; //implementación implícita
class MyTalk implements Talk {
name = 'Rx';
}
let charla2 = new MyTalk(); //implementación explícita
Visibilidad de métodos y propiedades de las clases
La visibilidad es public por defecto.
Constructores breves
constructor(public name: string) {}
Equivale a definir un atributo y fijar su valor:
public name: string;
constructor(name) {
this.name = name;
}
Sobrecarga de métodos
TypeScript soporta sobrecarga de métodos siempre que el número de argumentos de la función sobrecargada sea siempre igual:
function reverse(string: string): string;
function reverse<T>(array: T[]): T[];
function reverse<T>(
stringOrArray: string | T[]
): string | T[] {
return typeof stringOrArray === "string"
? stringOrArray
.split("")
.reverse()
.join("")
: stringOrArray.slice().reverse();
}
Las dos primeras son las posibles combinaciones aceptadas por typescript. La última debe ser la implementación de la función.
Tipos unión
La propiedad solamente podrá tomar uno de los valores definidos.
pos: ‘North’ | ‘East’;
Definición de tipos
Podemos definir nuevos tipos con type
type PuntoCardinal: 'Norte' | 'Sur' | 'Este' | 'Oeste'
let p: PuntoCardinal
Generics
Hay funciones o clases que pueden generalizarse sobre cualquier tipo de dato o sobre un conjunto de tipos. En typescript podemos definir dichas funciones o clase haciendo uso de los genéricos.
function identity<T>(arg: T): T {
return arg
}