Domando a Complexidade do Desenvolvimento Web com...
-
Upload
truongquynh -
Category
Documents
-
view
219 -
download
0
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/
#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