typescript para javeros: cómo programar web front-end y sentirse como en casa
TRANSCRIPT
Except where otherwise noted, this work is licensed under: http://creativecommons.org/licenses/by-nc-sa/3.0/
TypeScript para JaverosCómo programar web front-end y sentirse como en casa
Leganés, 11 y 12 de febrero
Micael Gallego
Características● Imperativo● Funcional (expresiones lambda)● Recolector de basura● Tipos estáticos● Orientado a objetos (con clases)● Modularidad con paquetes
Características● Imperativo● Funcional ● Recolector de basura● Tipos dinámicos● Orientado a objetos (con prototipos)● Sin modularidad
ES5
Tipos dinámicos● El compilador no te ayuda
● Hay que ejecutar los tests (si tienes)● El IDE tampoco te ayuda
● No se puede refactorizar de forma automática● El autocompletar es muy limitado● La documentación integrada sólo aparece en
casos muy evidentes● No se puede navegar a la implementación
ES5
Orientado a objetoscon prototipos
● Existen 3 formas diferentes de implementar “clases”
● Prototipos “a mano”● Simulación de clases con librerías● Patrón módulo usando clousures
● Los patrones de diseño OO no se pueden aplicar directamente
ES5
Sin modularidad● Para independizar código tienes que usar
patrones basados en funciones
ES5
(function() {
var variableTemporal = "a"; //Otro código…
}());
Immediately-Invoked Function Expression (IIFE)
Características● Framework de desarrollo de aplicaciones web
AJAX / SPA
● El back-end y front-end se desarrollan en Java
● En sus primeras versiones tenía muchos inconvenientes
● Pesado. Mucho tiempo de compilación● Sistema de componentes propio (no bootstrap)● Protocolo de comunicación propio
Características● La versión 2.8 ha mejorado mucho
● JsInterop: Permite integrar fácilmente código Java y JavaScript
● Se soporta Java 8 (expresiones lambda)package com.acme;
@JsTypeclass Foo {
public int x; public int y;
public int sum() { return x + y; }}
Java
var foo = new com.acme.Foo();
foo.x = 40;foo.y = 2;
foo.sum(); JS
Características● No lo considero una tecnología de front-end
genérica
● Lo usaría solo para portar código Java existente a front-end con poco coste
https://news.ycombinator.com/item?id=8554339
Características● Añade tipos estáticos a JavaScript ES6
● Inferencia de tipos● Tipos opcionales
● El compilador genera código JavaScript ES5 (compatible con los navegadores web actuales)
● Orientado a Objetos con clases (no como ES5)
● Anotaciones (ES7)
http://www.typescriptlang.org/
Características● Mejoras debidas a JavaScript ES6 (ES2015)
● Orientación a Objetos con clases● Arrow functions con captura de this● Let● Estructuras de datos● Módulos
● Mejoras debidas a JavaScript ES7● Anotaciones● Async / await
Ventajas frente a JavaScript● Con el tipado estático el compilador puede verificar
la corrección de muchas más cosas que con el tipado dinámico
● Los programas grandes son menos propensos a errores
● Los IDEs y editores pueden: Autocompletar, Refactorizar, Navegar a la definición
● Muy parecido a Java y C#
Facilidad de adopción para JavaScripters● Los tipos son opcionales● La inferencia de tipos permite no tener que
escribir los tipos constantemente● En realidad es JavaScript con más cosas, así que
todo lo conocido se puede aplicar● Un mismo proyecto puede combinar JS y TS, lo
que facilita migrar un proyecto existente
export class Empleado {
private nombre:string; private salario:number;
constructor(nombre:string, salario:number){ this.nombre = nombre; this.salario = salario; }
getNombre(){ return this.nombre; }
toString(){ return "Nombre:"+this.nombre+ ", Salario:"+this.salario; }}
TypeScript
Orientación a ObjetosTypeScript vs JavaScript ES5
export class Empleado {
private nombre:string; private salario:number;
constructor(nombre:string, salario:number){ this.nombre = nombre; this.salario = salario; }
getNombre(){ return this.nombre; }
toString(){ return "Nombre:"+this.nombre+ ", Salario:"+this.salario; }}
Clase en TypeScript
function Empleado(nombre, salario){
this.nombre = nombre; this.salario = salario;}
Empleado.prototype.getNombre = function(){ return nombre;}; Empleado.prototype.toString = function(){ return "Nombre:"+this.nombre+", Salario:"+this.salario;};
Simulación de clase en JS ES5 con prototipos
public class Empleado { private String nombre; private double salario;
public Empleado(String nombre, double salario){ this.nombre = nombre; this.salario = salario; }
public String getNombre(){ return nombre; }
public String toString(){ return "Nombre:"+nombre+ ", Salario:"+salario; }}
Clase en Javaexport class Empleado {
private nombre:string; private salario:number;
constructor(nombre:string, salario:number){ this.nombre = nombre; this.salario = salario; }
getNombre(){ return this.nombre; }
toString(){ return "Nombre:"+this.nombre+ ", Salario:"+this.salario; }}
Clase en TypeScript
Orientación a ObjetosTypeScript vs Java
public class Empleado { private String nombre; private double salario;
public Empleado(String nombre, double salario){ this.nombre = nombre; this.salario = salario; }
public String getNombre(){ return nombre; }
public String toString(){ return "Nombre:"+nombre+ ", Salario:"+salario; }}
Clase en Javaexport class Empleado {
private nombre:string; private salario:number;
constructor(nombre:string, salario:number){ this.nombre = nombre; this.salario = salario; }
getNombre(){ return this.nombre; }
toString(){ return "Nombre:"+this.nombre+ ", Salario:"+this.salario; }}
Clase en TypeScript
Orientación a ObjetosTypeScript vs Java
public class Empleado { private String nombre; private double salario;
public Empleado(String nombre, double salario){ this.nombre = nombre; this.salario = salario; }
public String getNombre(){ return nombre; }
public String toString(){ return "Nombre:"+nombre+ ", Salario:"+salario; }}
Clase en Javaexport class Empleado {
private nombre:string; private salario:number;
constructor(nombre:string, salario:number){ this.nombre = nombre; this.salario = salario; }
getNombre(){ return this.nombre; }
toString(){ return "Nombre:"+this.nombre+ ", Salario:"+this.salario; }}
Clase en TypeScript
Orientación a ObjetosTypeScript vs Java
public class Empleado { private String nombre; private double salario;
public Empleado(String nombre, double salario){ this.nombre = nombre; this.salario = salario; }
public String getNombre(){ return nombre; }
public String toString(){ return "Nombre:"+nombre+ ", Salario:"+salario; }}
Clase en Javaexport class Empleado {
private nombre:string; private salario:number;
constructor(nombre:string, salario:number){ this.nombre = nombre; this.salario = salario; }
getNombre(){ return this.nombre; }
toString(){ return "Nombre:"+this.nombre+ ", Salario:"+this.salario; }}
Clase en TypeScript
Orientación a ObjetosTypeScript vs Java
public class Empleado { private String nombre; private double salario;
public Empleado(String nombre, double salario){ this.nombre = nombre; this.salario = salario; }
public String getNombre(){ return nombre; }
public String toString(){ return "Nombre:"+nombre+ ", Salario:"+salario; }}
Clase en Javaexport class Empleado {
private nombre:string; private salario:number;
constructor(nombre:string, salario:number){ this.nombre = nombre; this.salario = salario; }
getNombre(){ return this.nombre; }
toString(){ return "Nombre:"+this.nombre+ ", Salario:"+this.salario; }}
Clase en TypeScript
Orientación a ObjetosTypeScript vs Java
public class Empleado { private String nombre; private double salario;
public Empleado(String nombre, double salario){ this.nombre = nombre; this.salario = salario; }
public String getNombre(){ return nombre; }
public String toString(){ return "Nombre:"+nombre+ ", Salario:"+salario; }}
Clase en Javaexport class Empleado {
private nombre:string; private salario:number;
constructor(nombre:string, salario:number){ this.nombre = nombre; this.salario = salario; }
getNombre(){ return this.nombre; }
toString(){ return "Nombre:"+this.nombre+ ", Salario:"+this.salario; }}
Clase en TypeScript
Orientación a ObjetosTypeScript vs Java
import { Empleado } from "./Empleado";
let emps = new Array<Empleado>();
emps.push(new Empleado('Pepe', 500));emps.push(new Empleado('Juan', 200));
for(let emp of emps){ console.log(emp.getNombre());}
empleados.forEach(emp => { console.log(emp);});
Módulos / Variables / for / lambda
List<Empleado> emps = new ArrayList<>();
emps.add(new Empleado('Pepe', 500));emps.add(new Empleado('Juan', 200));
for(Empleado emp : emps){ System.out.println(emp.getNombre());}
empleados.forEach(emp -> { System.out.println(emp);});
Java
import { Empleado } from "./Empleado";
let emps = new Array<Empleado>();
emps.push(new Empleado('Pepe', 500));emps.push(new Empleado('Juan', 200));
for(let emp of emps){ console.log(emp.getNombre());}
empleados.forEach(emp => { console.log(emp);});
TypeScript
Módulos / Variables / for / lambda
List<Empleado> emps = new ArrayList<>();
emps.add(new Empleado('Pepe', 500));emps.add(new Empleado('Juan', 200));
for(Empleado emp : emps){ System.out.println(emp.getNombre());}
empleados.forEach(emp -> { System.out.println(emp);});
Java
import { Empleado } from "./Empleado";
let emps = new Array<Empleado>();
emps.push(new Empleado('Pepe', 500));emps.push(new Empleado('Juan', 200));
for(let emp of emps){ console.log(emp.getNombre());}
empleados.forEach(emp => { console.log(emp);});
TypeScript
En Java las clases de la misma carpeta se pueden usar sin importar.
En TypeScript se tienen que importar porque cada fichero es un módulo distinto
Módulos / Variables / for / lambda
List<Empleado> emps = new ArrayList<>();
emps.add(new Empleado('Pepe', 500));emps.add(new Empleado('Juan', 200));
for(Empleado emp : emps){ System.out.println(emp.getNombre());}
empleados.forEach(emp -> { System.out.println(emp);});
Java
import { Empleado } from "./Empleado";
let emps = new Array<Empleado>();
emps.push(new Empleado('Pepe', 500));emps.push(new Empleado('Juan', 200));
for(let emp of emps){ console.log(emp.getNombre());}
empleados.forEach(emp => { console.log(emp);});
TypeScript
En Java usamos List y ArrayList del SDK.
En TypeScript usamos el Array nativo de JavaScript
Módulos / Variables / for / lambda
List<Empleado> emps = new ArrayList<>();
emps.add(new Empleado('Pepe', 500));emps.add(new Empleado('Juan', 200));
for(Empleado emp : emps){ System.out.println(emp.getNombre());}
empleados.forEach(emp -> { System.out.println(emp);});
Java
import { Empleado } from "./Empleado";
let emps = new Array<Empleado>();
emps.push(new Empleado('Pepe', 500));emps.push(new Empleado('Juan', 200));
for(let emp of emps){ console.log(emp.getNombre());}
empleados.forEach(emp => { console.log(emp);});
TypeScript
En Java List el método es “add”
En TypeScript Array el método es “push”
Módulos / Variables / for / lambda
List<Empleado> emps = new ArrayList<>();
emps.add(new Empleado('Pepe', 500));emps.add(new Empleado('Juan', 200));
for(Empleado emp : emps){ System.out.println(emp.getNombre());}
empleados.forEach(emp -> { System.out.println(emp);});
Java
import { Empleado } from "./Empleado";
let emps = new Array<Empleado>();
emps.push(new Empleado('Pepe', 500));emps.push(new Empleado('Juan', 200));
for(let emp of emps){ console.log(emp.getNombre());}
empleados.forEach(emp => { console.log(emp);});
TypeScript
Módulos / Variables / for / lambda
List<Empleado> emps = new ArrayList<>();
emps.add(new Empleado('Pepe', 500));emps.add(new Empleado('Juan', 200));
for(Empleado emp : emps){ System.out.println(emp.getNombre());}
empleados.forEach(emp -> { System.out.println(emp);});
Java
import { Empleado } from "./Empleado";
let emps = new Array<Empleado>();
emps.push(new Empleado('Pepe', 500));emps.push(new Empleado('Juan', 200));
for(let emp of emps){ console.log(emp.getNombre());}
empleados.forEach(emp => { console.log(emp);});
TypeScript
Módulos / Variables / for / lambda
Ventajas respecto a JavaCaracterísticas que gustarán a los
desarrolladores Java porque simplifica patrones comunes
interface SquareConfig { color: string; width?: number;}
Ventajas respecto a JavaObjetos literales con verificación y sintaxis compacta
function createSquare(config: SquareConfig){ ...}
createSquare({color: "black"});createSquare({color: "black", width: 20});
interface SquareConfig { color: string; width?: number;}
Ventajas respecto a JavaObjetos literales con verificación y sintaxis compacta
function createSquare(config: SquareConfig){ ...}
createSquare({color: "black"});createSquare({color: "black", width: 20});
class Animal { private name:string; constructor(name: string) {
this.name = name; }}
Ventajas respecto a JavaSintaxis compacta de definición de “beans”
class Animal { constructor(private name: string) { }}
class Animal { private name:string; constructor(name: string) {
this.name = name; }}
Ventajas respecto a JavaSintaxis compacta de definición de “beans”
class Animal { constructor(private name: string) { }}
class Animal { eat() { } }class Dog extends Animal { woof() { } }class Cat extends Animal { meow() { } }
var pet: Animal = undefined;if (pet instanceof Dog) { pet.woof();} else if (pet instanceof Cat) { pet.meow();} else { pet.eat();}
Ventajas respecto a JavaType guards Instanceof / typeof
class Animal { eat() { } }class Dog extends Animal { woof() { } }class Cat extends Animal { meow() { } }
var pet: Animal = undefined;if (pet instanceof Dog) { pet.woof();} else if (pet instanceof Cat) { pet.meow();} else { pet.eat();}
Ventajas respecto a JavaType guards Instanceof / typeof
Limitaciones respecto a Java● El código se ejecuta en una JavaScript VM, se
aplican todas las limitaciones del mismo● No hay números de 64 bits (ni long ni double)● No hay concurrencia con memoria
compartida● El control del recolector de basura no permite
implementar weak / soft references
Programación asíncronaSimulación de sincronía con async / await
http://www.sitepoint.com/javascript-goes-asynchronous-awesome/
Editores / IDEsHay plugins para la mayoría de los editores / IDEs
Sublime Text Visual Studio Code WebStorm
Editores / IDEsHay plugins para la mayoría de los editores / IDEs
Sublime Text Visual Studio Code WebStorm
62
Atom / atom-typescript
https://atom.io/packages/atom-typescript
Angular 2 recomienda usar TypeScript
import {Component} from 'angular2/core';
@Component({selector: 'app',templateUrl: 'app.html'
})export class AppComponent { name = 'Anybody'; }
app.component.ts
<h1>Hello {{name}}!</h1>
app.html
Incluso los editores onlineTypeScript se puede transpilar a ES5 directamente en el propio browser
System.config({ transpiler: 'typescript', typescriptOptions: { emitDecoratorMetadata: true }, map: { app: "./src" }, packages: { app: { main: './main.ts', defaultExtension: 'ts' } }});