Domando a Complexidade do Desenvolvimento Web com...

Post on 11-Nov-2018

219 views 0 download

Transcript of Domando a Complexidade do Desenvolvimento Web com...

Domando a complexidade do desenvolvimento Web

com TypeScript

Elemar Jr

Elemar Júnior

Microsoft Most Valuable Professional (MVP)

Arquiteto de Soluções na Promob há 17 anos

elemarjr.net

github.com/elemarjr

twitter.com/elemarjr

linkedin.com/elemarjr

Por que TypeScript? Por que agora?

#0. JavaScript é universal

#1. Você sabe JavaScript?

#2 E o seu time, sabe?

function sortByName(a) {var result = a.slice(0);result.sort(function(x, y) {

return x.name.localCompare(y.name);});return result;

}

O que você acha desse código?

E deste código aqui?

function buildName(firstName) {var restOfName = [];for (var _i = 1; _i < arguments.length; _i++) {

restOfName[_i - 1] = arguments[_i];}return firstName + " " + restOfName.join(" ");

}

#3 Desenvolvimento em

grande escala com JavaScript

é difícil.

Anders Hejlsberg

Muito código inteligente (!?)

var Geometry;(function (Geometry) {

var Point = (function () {function Point(x, y) {

if (x === void 0) { x = 0; }if (y === void 0) { y = 0; }this.x = x;this.y = y;

}Point.prototype.distanceTo = function (other) {

var dx = this.x - other.x;var dy = this.y - other.y;return Math.sqrt(dx * dx + dy * dy);

};return Point;

})();Geometry.Point = Point;

})(Geometry || (Geometry = {}));

#4 TypeScript é OPT-IN

TypeScript é

(1) um “superset“ tipado de JavaScript que

(2) compila para JavaScript.

Compilador

TypeScriptTS JS

function sortByName(a: any[]) {var result = a.slice(0);result.sort(function(x, y) {

return x.name.localCompare(y.name);});return result;

}

Adicionando um Type Annotation

Com suporte a “Structural Typing”

interface Entity {name: string;

}

function sortByName(a: Entity[]) {var result = a.slice(0);result.sort(function(x, y) {

return x.name.localeCompare(y.name);});return result;

}

Sem impactos para o código JS

Qualquer browser, host ou SO

#4 Compatível com a

evolução do ECMAScript

#5 Tooling

O que é TypeScript?

Habilita ferrametas de Refactoring

interface Entity {name: string;

}

function sortByName(a: Entity[]) {var result = a.slice(0);result.sort(function(x, y) {

return x.name.localeCompare(y.name);});return result;

}

Sublime Text

function calculateArea(height: number, width: number): number {return height * width;

}

http://developer.telerik.com/featured/the-rise-of-typescript/

Sublime Text

http://developer.telerik.com/featured/the-rise-of-typescript/

#6 Open Source

https://github.com/Microsoft/TypeScript/

#7 Structural Typing

interface Point {x: number;y: number;

}

var p: Point = {x: 10, y: 20

}

var p2 = {x: 10, y: 20

}

Com suporte a “Structural Typing”

interface Point {x: number;y: number;z?: number;

}

var p: Point = {x: 10, y: 20

}

Com suporte a “Structural Typing”

Com suporte a “Structural Typing”

interface Product {name: string;price: number;getName(): string;setName(value: string): void;

}

var p: Product ={

name: "Promob Plus",price: 2500,getName: function () { return this.name; },setName: function (value) { this.name = value; }

}

#8 Generics

Generics

interface Entity {name: string;

}

function sortByName(a: Entity[]) {var result = a.slice(0);result.sort(function(x, y) {

return x.name.localeCompare(y.name);});return result;

}

var people = [{ name: "Gabriel", age: 15 },{ name: "Elemar", age: 35 },{ name: "Ana", age: 18 }

];

var sorted = sortByName(people);

sorted[0].

Generics

interface Entity {name: string;

}

function sortByName<T extends Entity>(a: T[]) {var result = a.slice(0);result.sort(function(x, y) {

return x.name.localeCompare(y.name);});return result;

}

var people = [{ name: "Gabriel", age: 15 },{ name: "Elemar", age: 35 },{ name: "Ana", age: 18 }

];

var sorted = sortByName(people);

sorted[0].

Generics não tem “peso” em tempo de execuçãoTS JS

interface Entity {name: string;

}

function sortByName<T extends Entity>(a: T[]) {var result = a.slice(0);result.sort(function (x, y) {

return x.name.localeCompare(y.name)})

}

function sortByName(a) {var result = a.slice(0);result.sort(function (x, y) {

return x.name.localeCompare(y.name);});

}

#9 Lambdas

Lambda, Lambda!TS JS

function sortByName<T extends Entity>(a: T[]) {var result = a.slice(0);result.sort(

(x, y) => x.name.localeCompare(y.name));

}

function sortByName(a) {var result = a.slice(0);result.sort(function(x, y) {

return x.name.localeCompare(y.name);});

}

interface Entity {name: string;

}

function sortBy<T extends Entity>(a: T[], keyOf: (item: T) => any) {const result = a.slice(0);result.sort((x, y) => {

var keyOfX = keyOf(x);var keyOfY = keyOf(y);return keyOfX > keyOfY ? 1 : keyOfX < keyOfY ? -1 : 0;

});return result;

}

var people = [{ name: "Gabriel", age: 15 },{ name: "Elemar", age: 35 },{ name: "Ana", age: 18 }

];

var sorted = sortBy(people, x => x.name);

Lambda, Lambda!

#10 Classes

Classes sem improvisoTS JS

class Point {x: number;y: number;

}

var p = new Point();p.x = 3;p.y = 4;

var Point = (function () {function Point() {}return Point;

})();var p = new Point();p.x = 3;p.y = 4;

Classes sem improvisoTS JS

class Point {x: number;y: number;

}

var p = new Point();p.x = 3;p.y = 4;

var Point = (function () {function Point() {}return Point;

})();var p = new Point();p.x = 3;p.y = 4;

ConstrutoresTS JS

class Point {x: number;y: number;constructor(x: number, y: number) {

this.x = x;this.y = y;

}}var p = new Point(3, 4);

var Point = (function () {function Point(x, y) {

this.x = x;this.y = y;

}return Point;

})();var p = new Point(3, 4);

Construtores – Inicialização simplesTS JS

class Point {constructor(

public x: number, public y: number)

{}}var p = new Point(3, 4);

var Point = (function () {function Point(x, y) {

this.x = x;this.y = y;

}return Point;

})();var p = new Point(3, 4);

MétodosTS JS

class Point {constructor(

public x: number,public y: number) {

}

distanceTo(other: Point) {var dx = this.x - other.x;var dy = this.y - other.y;return Math.sqrt(dx * dx + dy * dy);

}}var p = new Point(3, 4);

var Point = (function () {function Point(x, y) {

this.x = x;this.y = y;

}Point.prototype.distanceTo = function (other) {

var dx = this.x - other.x;var dy = this.y - other.y;return Math.sqrt(dx * dx + dy * dy);

};return Point;

})();var p = new Point(3, 4);

Parâmetros múltiplosTS JS

function buildName(firstName: string,...restOfName: string[]) {

return firstName + " " + restOfName.join(" ");}

var name = buildName("Elemar","Rodrigues","Severo","Junior");

function buildName(firstName) {var restOfName = [];for (var _i = 1; _i < arguments.length; _i++) {

restOfName[_i - 1] = arguments[_i];}return firstName + " " + restOfName.join(" ");

}

Membros privadosTS JS

class Point {private distanceToOrigin: number;constructor(

public x: number = 0,public y: number = 0) {this.distanceToOrigin =

this.distanceTo(Point.zero);}

distanceTo(other: Point) {var dx = this.x - other.x;var dy = this.y - other.y;return Math.sqrt(dx * dx + dy * dy);

}

static zero = new Point(0, 0);}

var p = new Point(3, 4);

var Point = (function () {function Point(x, y) {

if (x === void 0) { x = 0; }if (y === void 0) { y = 0; }this.x = x;this.y = y;this.distanceToOrigin =

this.distanceTo(Point.zero);}Point.prototype.distanceTo = function (other) {

var dx = this.x - other.x;var dy = this.y - other.y;return Math.sqrt(dx * dx + dy * dy);

};Point.zero = new Point(0, 0);return Point;

})();var p = new Point(3, 4);

Membros estáticosTS JS

class Point {constructor(

public x: number,public y: number) {

}

distanceTo(other: Point) {var dx = this.x - other.x;var dy = this.y - other.y;return Math.sqrt(dx * dx + dy * dy);

}

static zero = new Point(0, 0);}var p = new Point(3, 4);

var Point = (function () {function Point(x, y) {

this.x = x;this.y = y;

}Point.prototype.distanceTo = function (other) {

var dx = this.x - other.x;var dy = this.y - other.y;return Math.sqrt(dx * dx + dy * dy);

};

Point.zero = new Point(0, 0);return Point;

})();var p = new Point(3, 4);

Valores default em argumentosTS JS

class Point {constructor(

public x: number = 0,public y: number = 0) { }

distanceTo(other: Point) {var dx = this.x - other.x;var dy = this.y - other.y;return Math.sqrt(dx * dx + dy * dy);

}

static zero = new Point(0, 0);}

var p = new Point(3, 4);

var Point = (function () {function Point(x, y) {

if (x === void 0) { x = 0; }if (y === void 0) { y = 0; }this.x = x;this.y = y;

}Point.prototype.distanceTo = function (other) {

var dx = this.x - other.x;var dy = this.y - other.y;return Math.sqrt(dx * dx + dy * dy);

};Point.zero = new Point(0, 0);return Point;

})();var p = new Point(3, 4);

RECREIO

DEMO: Starfield

http://elemarjr.github.io/demos/starfield.html

Abstraindo aplicação

interface IApp {init(): IApp;run();

}

window.onload = () => {new App()

.init()

.run();};

Implementação da aplicação

class App implements IApp {private engine: RenderingEngine;private stars: Array<IStar>;

init(): App {this.initEngine();this.initStars();return this;

}/*...*/run(): void {

var that = this;var iterate = () => {

that.engine.clear();that.stars.forEach((star) => star.update().draw(this.engine));setTimeout(iterate, 33);

};iterate();

}

Abstraindo uma entidade

interface IStar {position: Point3;shade: number;size: number;

update(): IStar;draw(engine: IRenderingEngine): IStar;

}

Abstraindo uma entidade

class Star implements IStar {position: Point3;size = 0;shade = 0;

constructor() {this.reset();this.position.z = Random.inRange(0, 32);

}

private reset(): void {this.position = Point3.random();

}

update(): IStar {this.position.z -= 0.2;if (this.position.z <= 0) this.reset();this.size = (1 - this.position.z / 32.0) * 5;this.shade = Math.floor((1 - this.position.z / 32.0) * 255);return this;

}

draw(engine: IRenderingEngine): IStar {engine.drawStar(this);return this;

}};

Ponto3

class Point3 {constructor(

public x: number,public y: number,public z: number) { }

static random(): Point3 {return new Point3(

Random.inRange(-20, 20),Random.inRange(-20, 20),Random.inRange(0, 32));

}}

Abstraindo um “RenderingEngine”

interface IRenderingEngine {clear(): void;drawStar(start: IStar): void;

}

Abstraindo um “RenderingEngine”

class RenderingEngine implements IRenderingEngine {private canvas: HTMLCanvasElement;private context: CanvasRenderingContext2D;

constructor(canvas: HTMLCanvasElement) {this.canvas = canvas;this.context = canvas.getContext("2d");

}

clear(): void {this.context.fillStyle = `rgb(0, 0, 0)`;this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);

}

drawStar(star: IStar): void {const k = 128 / star.position.z;const px = star.position.x * k + (this.canvas.width / 2);const py = star.position.y * k + (this.canvas.height / 2);if (px >= 0 && px <= this.canvas.width && py >= 0 && py <= this.canvas.height) {

const s = star.shade;this.context.fillStyle = `rgb(${s}, ${s}, ${s})`;this.context.fillRect(px, py, star.size, star.size);

}}

};

#11 Módulos

MódulosTS JS

module Geometry {export class Point {

constructor(public x: number = 0,public y: number = 0) {

}

distanceTo(other: Point) {var dx = this.x - other.x;var dy = this.y - other.y;return Math.sqrt(dx * dx + dy * dy);

}}

}

var Geometry;(function (Geometry) {

var Point = (function () {function Point(x, y) {

if (x === void 0) { x = 0; }if (y === void 0) { y = 0; }this.x = x;this.y = y;

}Point.prototype.distanceTo = function (other) {

var dx = this.x - other.x;var dy = this.y - other.y;return Math.sqrt(dx * dx + dy * dy);

};return Point;

})();Geometry.Point = Point;

})(Geometry || (Geometry = {}));

#12 Ótimo para explorar

bibliotecas de terceiros

Um TypeDefinition

// Type definitions for poly2tri v1.3.5// Project: http://github.com/r3mi/poly2tri.js/// Definitions by: Elemar Junior <https://github.com/elemarjr/>// Definitions: https://github.com/borisyankov/DefinitelyTyped

declare module poly2tri {

interface IPointLike {x: number;y: number;

}

class Point implements IPointLike {

x: number;y: number;

constructor(x: number, y: number);

toString(): string;

toJSON(): JSON;

set_zero(): Point;

set(x: number, y: number): Point;

#13 Muito mais coisas legais

Criação de objetos e atribuições facilitadasTS JS

function point(x: number, y: number, z: number) {return { x, y, z };

}

let {x, y} = point(10, 10, 5);

function point(x, y, z) {return { x: x, y: y, z: z };

}var _a = point(10, 10, 5), x = _a.x, y = _a.y;

Criação de objetos e atribuições facilitadasTS JS

let a = [1, 2, 3, 4, 5];let [first, ...rest] = a;let b = [first, ...rest, 10, 20, 30];

var a = [1, 2, 3, 4, 5];var first = a[0], rest = a.slice(1);var b = [first].concat(rest, [10, 20, 30]);

For .. ofTS JS

for (var element of b) {console.log(element);

}

for (var _i = 0; _i < b.length; _i++) {var element = b[_i];console.log(element);

}

Type Guards

Type Guards

Type Guards

Bônus: O futuro do TypeScript

Finalizando, typescript é ...

• Um superset para a JavaScript que compila para JavaScript, com

ótimo tooling

• Uma “ponte” para desenvolvedores acostumados com

linguagens tipadas

• Uma alternativa séria para redução da “curva de aprendizado”

• Ideal para sistemas grandes e complexos

• Uma antecipação do que estará disponível no futuro

(ECMAScript)

• Open Source

Muito obrigado.https://github.com/ElemarJR/feedback