TypeScript para Javeros. Por fin un lenguaje 'de verdad' en el browser

117
Por fin un lenguaje 'de verdad' en el browser TypeScript para Javeros 24 Mayo 2016

Transcript of TypeScript para Javeros. Por fin un lenguaje 'de verdad' en el browser

Por fin un lenguaje 'de verdad' en el browser

TypeScript para Javeros

24 Mayo 2016

2

¿Quién soy?

@micael_gallego

3

¿Quién soy?

developer

4

¿Quién soy?

developer

5

¿Quién soy?

developerFormación universitaria y

en empresas

Desarrollador Media ServerWebRTC Open Source

6

¿Quién soy?

developer

7

¿Quién soy?

JavaScripter aficionado...

8

¿Quién soy?

JavaScripter aficionado...

sufridor

9

¿Quién soy?

JavaScripter aficionado

10

¿Quién soy?

...pero prefiero Java

11

¿Quién soy?

12

¿Quién soy?

14

Características Imperativo Funcional (expresiones lambda) Recolector de basura Tipos estáticos Orientado a objetos (con clases) Modularidad con paquetes (y con .jars)

15

Funcional expresiones lambda

Java 8 streams

16

Orientado a objetos

17

Tipado estáticoErrores en tiempo de compilación

18

Tipado estáticoAutocompletar

19

Tipado estáticoRefactorizaciones automatizadas

20

Tipado estáticoDocumentación integrada en el IDE

21

22

23

¿Web front-end?

24

ES5

25

Características Imperativo Funcional Recolector de basura Tipado dinámico Orientado a objetos (con prototipos) Sin modularidad

ES5

26

Tipado dinámico 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

27

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

ES5

28

Orientado a objetoscon prototipos

ES5

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;}

var empleado = new Empleado("Pepe", 700);console.log( empleado.toString() );

29

Orientado a objetoscon prototipos

La herencia es “hacky” (aunque ellos dirán que no se usa mucho...)

Los patrones de diseño OO no se pueden aplicar directamente (ya que te los has aprendido...)

ES5

30

Sin modularidad Para independizar código tienes que usar

patrones basados en funciones O usar AMD, CommonJS, UMD...

ES5

(function() {

var variableTemporal = "a"; //Otro código…

}());

Immediately-Invoked Function Expression (IIFE)

31

y otras lindezas...¿this y that?

ES5

function Empleado(nombre, sueldo){ this.nombre = nombre; this.sueldo = sueldo;}

Empleado.prototype.alertaAlPulsar(button){

button.onclick = function(){ alert(this.nombre+" "+this.sueldo); }}

ERROR: this apunta al objeto en el que se ha generado el evento

32

y otras lindezas...WAT / === / !==

ES5

https://www.destroyallsoftware.com/talks/wat

33

ES5

34

¿Java en front-end?

35

36

37

38

39

¿ConvertirJava a JavaScript?

40

41

Google Web Toolkit En 2006 Google saca una herramienta para

convertir código Java a código JavaScript

JS ultraoptimizado y compatible con los

browsers “incompatibles” del momento

Librería de widgets

42

Google Web Toolkit Pero...

● Muy acoplado al backend escrito en Java (con su

propio protocolo de comunicación)

● Desarrollo muy pesado (compilador tardaba,

plugins para ejecutar Java en el navegador…)

● Complicado usar librerías JavaScript desde código

Java...

43

44

Nuevo GWT (2.8 beta) Desarrollado por la comunidad

Mucho más ligero, sin plugins en browsers

Mejor integración Java y JavaScript

No acoplado a backend Java (clientes REST)

Soporta Java 8 (lambda)

45

Nuevo GWT (2.8 beta) No es 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

46

¿Pero entonces qué c...o quieres?

47

Deseos de un Javero desarrollando web frontend

Un lenguaje orientado a objetos con clases y herencia

Tipado estático Buenas herramientas con autocompletar,

refactoring, navegación…

48

49

Deseos de un Javero desarrollando web frontend

Plugin de eclipse / IntelliJ / Netbeans Que esté maduro y se use en producción (que

no sea un proyecto en github de cuatro frikis) Que haya buena documentación en la red,

libros, video cursos...

50

Deseos de un Javero desarrollando web frontend

Que pueda usar cualquier librería JavaScript directamente sin complicaciones

Que también lo usen los hipsters frontenders JavaScripters para que no me miren mal

Que esté apoyado por la comunidad y por las empresas

51

52

Pues parece que vamos a tener suerte...

53

54

55

¿Qué es TypeScript? Un superconjunto de JavaScript que añade tipos

estáticos

Soporta orientación a objetos con clases y herencia

El compilador de TypeScript genera código JS que

se ejecuta en cualquier browser y en node.js

http://www.typescriptlang.org/ https://www.gitbook.com/book/basarat/typescript/details

56

57

¿Qué son ES6 y ES7?

ES6 es la última versión de JS (pero ningún navegador la entiende 100%)

A ES6 ahora le llaman ES2015 ES7 es la versión en desarrollo, aunque algunas

partes son bastante estables Algunas características de TypeScript se pueden

usar en JavaScript ES6

58

Más características de TS Funciones lambda (llamadas arrow functions) en

las que this no cambia de significado Módulos (exportar e importar elementos) Anotaciones Programación pseudo-síncrona con async / await Ámbito de variables de bloque (y error si se declara

dos veces) For each ...

59

Sólo tiene un pero… ;)

60

61

Satya NadellaCEO

62

Desde que llegó Nadella Microsoft está irreconocible

software libre

https://github.com/Microsoft/TypeScript

63

64

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

65

Clases Java vs TypeScript

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

66

Clases Java vs TypeScript

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

En Java las clases son públicas. En TypeScript las clases se exportan

67

Clases Java vs TypeScript

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

En TS los tipos se ponen tras el nombre con : (dos puntos)

68

Clases Java vs TypeScript

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

En TS el constructor es “constructor”

69

Clases Java vs TypeScript

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

En TS los tipos se infieren (si quieres), incluso en el tipo que devuelven los métodos

70

Clases Java vs TypeScript

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

En TS siembre que quieras acceder a un elemento de la clase tendrás que usar this.

71

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

72

Imports / Listas / foreach / lambdas

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

73

Imports / Listas / foreach / lambdas

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 son del mismo paquete. En TS cada fichero es un módulo, por eso hay que importar desde otros ficheros

74

Imports / Listas / foreach / lambdas

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 TS las variables se declaran con let y tienen ámbito de bloque y no se pueden declarar dos veces. Se podría usar var (como JS), pero el ámbito sería la función y se podrían redeclarar

75

Imports / Listas / foreach / lambdas

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 TS las variables se pueden declarar con tipo (después de :), pero es opcional porque el tipo se infiere de la inicialización. En Java no lo veremos hasta Java 9 o Java 10

76

Imports / Listas / foreach / lambdas

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 generificados del API.En TS usamos el Array nativo de JS generificado por TS.

77

Imports / Listas / foreach / lambdas

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 el Array de JS el método es “push”

78

Imports / Listas / foreach / lambdas

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

La sintaxis del foreach es muy parecida en Java y TS. En TS está basado en iteradores (como en Java)

79

Imports / Listas / foreach / lambdas

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

Las expresiones lambda de Java se llaman arrow function en TS.Se diferencian en la “flecha” con – o con =

80

Lambdas / Arrow functions

int num = 0;

empleados.forEach(emp -> num++);

System.out.println(num);

Java

let num = 0;

empleados.forEach(emp => num++);

console.log(num);

TypeScript

En Java no se puede acceder a una variable que no sea final (declarada o efectiva) desde una lambda. En TS (como en JS) incluso se puede cambiar el

valor de la variable desde la propia arrow function

ERROR

81

Uso de this con la arrow function

function Empleado(nombre, sueldo){ this.nombre = nombre; this.sueldo = sueldo;}

Empleado.prototype.alerta(button){ var that = this; button.onclick = function(e){ alert(that.nombre); }}

En TS una arrow function permite usar this y siempre apunta al objeto (como Java). En JS si usas funciones this puede cambiar de valor (y es

necesario usar that)

export class Empleado {

private nombre:string, private sueldo:number){}

alerta(button:HTMLButtonElement){ button.onclick = e => { alert(this.nombre); } }}

JavaScript TypeScript

82

Anotaciones

import {Component} from 'angular2/core';

@Component({selector: 'app',templateUrl: 'app.component.html'

})export class AppComponent { }

83

Ventajas de TS respecto a JavaCaracterísticas que gustarán a los

desarrolladores Java porque simplifica patrones comunes en Java

84

Definición de atributos inicializados en constructor

class Animal {

private name:string;

constructor(name: string) { this.name = name;

}}

85

class Animal { constructor(private name: string) { }}

class Animal { private name:string; constructor(name: string) {

this.name = name; }}

class Animal { constructor(private name: string) { }}

En TS se puede declarar un atributo e inicializar su valor desde el constructor declarando ese atributo como parámetro del constructor y usando el modificar de visibilidad

Definición de atributos inicializados en constructor

86

class Foo { get bar() { return ...; }

set bar(bar: boolean) { ... }}

Getter / Setter con sintaxis de atributo

let foo = new Foo();

if(foo.bar){ foo.bar = false;}

87

class Foo { get bar() { return ...; }

set bar(bar: boolean) { ... }}

Getter / Setter con sintaxis de atributo

let foo = new Foo();

if(foo.bar){ foo.bar = false;}

88

class Animal { eat() { } }class Dog extends Animal { woof() { } }class Cat extends Animal { meow() { } }

let pet: Animal = ...;if (pet instanceof Dog) { pet.woof();} else if (pet instanceof Cat) { pet.meow();} else { pet.eat();}

Type guards Instanceof / typeof

Disponible también en

Animal

eat()

Animal

eat()

Dog

woof()

Animal

eat()

Cat

meow()

89

interface SquareConfig { color: string; width?: number;}

Objetos literales “tipados”

let config: SquareConfig;

config = {color: "black"};config = {color: "black", width: 20};

90

interface SquareConfig { color: string; width?: number;}

Objetos literales “tipados”

let config: SquareConfig;

config = {color: "black"};config = {color: "black", width: 20};

91

Programación asíncronaSimulación de sincronía con async / await

function loadData() { return getJSON('data.json') .then(data=>{

addHtmlToPage(data);

return data;

}).catch(err => { console.log(err) });}

async function loadData() { try {

let data = await getJSON('data.json');

addHtmlToPage(data); return data;

} catch(err){ console.log(err); } }

92

Programación asíncronaSimulación de sincronía con async / await

function loadData() { return getJSON('data.json')

.then(data=>{

addHtmlToPage(data);

return data;

}).catch(err => { console.log(err) });}

async function loadData() { try {

let data = await getJSON('data.json');

addHtmlToPage(data); return data;

} catch(err){ console.log(err); } }

93

Algunas cosas “raras”Para poder se compatible con JavaScript

94

Tipos unión

let id: string | number;

id = 3;...Id = “3”;

if(typeof id === “string”){ ...}

En JS es habitual que ciertas variables puedan tener la misma

información aunque se represente con varios “tipos”.

TS permite definir variables con varios tipos

95

Compatibilidad de tipos estructural

interface User { name: string;}

class Profile { constructor(public name:string){}}

let u: User;u = { name: "Pepe" };u = new Profile("Pepe");

96

interface User { name: string;}

class Profile { constructor(public name:string){}}

let u: User;u = { name: "Pepe" };u = new Profile("Pepe");

Compatibilidad de tipos estructural

Un objeto Profile puede asignarse a una variable

de tipo User porque tiene un atributo name

97

Sobrecarga de métodos “especial”class TestClass {

someMethod(p1: string): void; someMethod(p1: number, p2: string): void; someMethod(p1: string | number, p2?: string): void {

if (typeof p1 === "string"){ console.log("p1"); } else if(p2){ console.log("p2"); } }}

Dos métodos con el mismo nombre deben tener una única

implementación que detecte cual ha sido llamado.

La implementación tiene que cubrir todas las cabeceras

98

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

99

El lenguaje tiene buena pinta...¿Pero hay herramientas? Soporte? Librerías

compatibles? Lo usa alguien?

100

Editores / IDEsHay plugins para la mayoría de los editores / IDEs

Sublime Text Visual Studio Code WebStorm

101

WebStorm 11

102

WebStorm 11

103

WebStorm 11

104

Atom / atom-typescript

https://atom.io/packages/atom-typescript

105

Eclipse / typescript.java

https://github.com/angelozerr/typescript.java

106

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'    }  }});

107

TypeScript

coffeescript

ES6

Popularidad de TypeScript

108

¿Quién usa TypeScript?

Seguro que 4 raros… porque ser JavaScripter y que te gusten el

tipado estático...

109

ngular 2TypeScript es el lenguaje recomendado

Prácticamente todos los ejemplos y tutoriales están implementados con TypeScript

110

Angular 2

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

111

Otros frameworks de moda se pueden usar con TypeScript

112

Y tus librerías JS de toda la vida...

113

¿Y los JavaScripters qué opinan?

Dirán que es una mierda… fijo

114

Los JavaScripters no se quejan mucho

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

115

ConclusionesDe un aficionado / sufridor

116

A los que nos gusta nuestro compilador y nuestros IDEs por fin tenemos un lenguaje de verdad en el browser

Con este lenguaje desarrollar en Node.js y en el browser será como estamos acostumbrados

Muchos desarrolladores backend se pasarán a front con TypeScript

Existen muchas historias de éxito en la red

117

¿Preguntas?

Gracias...