• Nenhum resultado encontrado

Introdução ao Typescript

N/A
N/A
Protected

Academic year: 2021

Share "Introdução ao Typescript"

Copied!
96
0
0

Texto

(1)

Introdução ao Typescript

(2)

Introdução ao Typescript

• Linguagem criada e desenvolvida pela Microsoft de forma open source;

• Superset da linguagem Javascript (mantém a compatibilidade), em que a orientação a objetos e tipificação de valores assume um papel fundamental no aumento de

produtividade e na redução de erros associados à geração de código Javascript; • O Typescript depois de compilado gera código Javascript;

(3)

Introdução ao Typescript

• Qualquer ambiente Web que aceita Javascript irá aceitar Typescript. Site oficial da linguagem. Frameworks como Angular, Ionic e o NodeJS trabalham com Typescript

(4)

Introdução ao Typescript

• Possui uma sintaxe do tipo clássica referente aos conceitos de OO; • Permite herança, recurso não disponível em Javascrip clássico.

• Temos o conceito de módulos (pacotes, namespaces) também ausente em Javascript • Você não pode mexer na estrutura da classe sem receber um alerta;

• Existe o papel de construtores e pode-se inserir parâmetros opcionais (?). Vantagens

(5)

Introdução ao Typescript

• Mais algumas diferenças: Vantagens

Classe com propriedades automáticas Declaração automática

de propriedade, Basta usar o construtor para isso, aumentando a

produtividade.

Tipagem forte, depois de declarada, o tipo não

pode ser alterado, podendo assim ser verificado pelo compilador. Inferência de tipo, aonde o compilador define o tipo da variável.

(6)

Iremos usar o NodeJs, que é um servidor de aplicações web Javascript. O software

que iremos criar não precisará do Node e sim do browser e dos códigos. Mas

essa ferramenta é importante para o desenvolvimento. Por exemplo, fornecendo o NPM. Node.js e NPM

(7)

Gerenciador de pacotes Javascrip. Ou seja, acessamos um repositório de bibliotecas para projetos Javascript Node.js e NPM

(8)

Iremos usar essa ferramenta dentre as várias existentes para a

criação do código em Type Script

Visual Studio Code

Como instalar o Typescript

(9)

Slide 8

(10)

Como instalar o Typescript

• Lanch.json, task.json e tsconfig.json para fazer a instalação 1) Utilizamos o npm do compilador Typescript 2) Podemos testar a instalação requisitando a versão do programa. Instalando o compilador

(11)

Como instalar o Typescript

1) Crie uma pasta e faça o acesso

via VSCode.

2) Crie um arquivo com extensão “.ts” e digite o

código. Testando o VSCode e o compilador

3) Podemos usar o primeiro comando para compilar e o

segundo para rodar o arquivo “.js” criado. https://www.typescriptlang.org/play/ 4) Uma outra forma de testar é utilizando o compilador online da linguagem

(12)

Como instalar o Typescript

Testando o VSCode e o compilador

3) As propriedades significam respectivamente: Versão do compilador, Comando para compilação, exibir erros no console e, por último,

qual utilitário pode ser usado para apresentar soluções.

https://code.visualstudio.com/docs/typescript/typescript-compiling https://www.youtube.com/watch?v=Hs6XWwQUs_A

1) Para evitar os dois passos executados no slide anterior, usamos um recurso do VSCode chamado task runner, executamos o código através de uma tarefa, assim temos que criar um arquivo com os

passos que a ferramenta deve executar.

tasks.json 2) Crie uma pasta

”.vscode” e dentro dessa pasta um arquivos chamado tasks.json (Terminal >

Run Build Task...)

{ "version": "2.0.0", "tasks": [ { "type": "typescript", "tsconfig": "tsconfig.json", "problemMatcher": [ "$tsc" ], "group": { "kind": "build", "isDefault": true } } ] }

(13)

{ "compilerOptions": { "target": "es5", "module": "commonjs", "sourceMap": true } }

Como instalar o Typescript

Testando o VSCode e o compilador

2) As propriedades significam respectivamente: Versão do javascript, qual módulo padrão está

sendo utilizando e por isso, os arquivos de mapeamento para Debug devem ser gerados.

1) Agora temos que informar as configurações

do projeto em questão, para isso crie um arquivo chamado tsconfig.json na

raiz do projeto.

(14)

"version": "0.2.0",

"configurations": [ {

"type": "node",

"request": "launch",

"name": "Typescript debug",

"program": "${workspaceFolder}/app.ts", "outFiles": [ "${workspaceFolder}/**/*.js" ] }, { "type": "node", "request": "attach",

"name": "Attach to process",

"address": "localhost", "port": 5858, "outFiles": [ "${workspaceFolder}/**/*.js" ] } ] }

Como instalar o Typescript

Testando o VSCode e o compilador

2) Informe o nome do arquivo principal da aplicação.

1) Agora temos que informar as configurações

do projeto para Debug, para isso crie um arquivo

chamado laungh.json na pasta “.vscode”.

laungh.json https://code.visualstudio.com/docs/typescript/typescript-compiling

(15)

Como instalar o Typescript

Testando o VSCode e o compilador

2) Logo em seguinda executar com ou sem o DEBUG CRTL+F5 1) Depois de configurado, temos que compilar o script com os comandos

CRLT+SHIT+B.

(16)

• Veja um outro exemplo de código

Como instalar o Typescript

Crie um arquivo com extensão “.ts” e digite o

código. Testando o VSCode e o compilador

(17)

function teste(i: number){ var teste; if (i === 10){ valor = 20; } else { valor = 30; }

console.log(valor); }

• A declaração de variáveis em Typescript segue a mesma conversão do Javascript, o qual é feita através da palavra reservada “var”. Infelizmente as variáveis declaradas dessa forma estão sujeitas ao chamado hoisting. Veja exemplo:

Tipos básicos

Variáveis

function teste(i: number){

if (i === 10){ var valor = 20; } else { var valor = 30; }

console.log(valor); }

2) Esse código não implica em erro, a declaração da

variável com “var” é transferida para o início

do escopo com o valor “undefined” 1) Ocorre erro?

(18)

• O ECMAScript 2015 (ECMAScript 6 ou Javascript 6) introduziu novos termos – let e const que podem ser utilizados em substituição ao termo var;

consté usado para introduzir valores constantes

letnão está sujeito a hoisting. Todas as declarações com este termo possui o âmbito do bloco onde foram

utilizadas

Tipos básicos

Variáveis

function teste(i: number){

if (i === 10){ let valor = 20; } else { let valor = 30; }

console.log(valor);

(19)

• Os tipos básicos introduzido pelo Typescrip são semelhantes aos que podem ser usados em Javascript. O tipo boolean recebe os valaores true ou false.

Tipos básicos

Boolean

var isNew: boolean = false;

isNew = true;

• Todos os números são do tipo number, não existe subtipos como integer ou float. Number

var age: number = 21;

var pi: number;

(20)

• Sempre que necessitamos de um texto, recorrermos ao tipo string. Os valores literais podem ser delimitados por aspas duplas ou simples.

Tipos básicos

String

var nome: String = ‘Não informado’;

nome = "Luis";

• Valor literal delimitados por caractere de acento de crase (`) e permitem criar strings multilinha ou expressões com placeholders utilizando ${xxx} .

Template strings

let nome = "Luis";

let expressao = ` Olá, ${nome}

tudo bem com você?`;

(21)

var list1: number[] = [1, 2, 3];

let i:any;

for(i in list1) {

console.log(list1[i]) }

var list2: Array<number> = [8,12,33];

console.log(`Primeiro elemento da lista2 => ${list2[0]}`);

var list3: number[]

list3 = [5, 4, 3];

list3.forEach( (p) => console.log(p) );

var alpha = ["a", "b", "c"];

var numeric = ["1", "2", "3"];

var alphaNumeric = alpha.concat(numeric);

console.log("alphaNumeric : " + alphaNumeric );

alphaNumeric.push("098");

console.log("alphaNumeric : " + alphaNumeric );

• Existem também um tipo que armazena um conjunto de valores do mesmo tipo, matriz unidimensional, a qual pode ser declarado de duas formas diferentes:

Tipos básicos

Array Compilador exige que a variável seja do tipo any ou string. Acessando um elemento específico Inserindo um elemento no final do array.

(22)

• Existem vários métodos para trabalhamos com arrays, pois eles são tratados como objetos pela linguagem:

Tipos básicos

Array

(23)

• Exemplos:

Tipos básicos

Array

https://www.tutorialspoint.com/typescript/typescript_arrays.htm

//---var marks:number[] = [58, 68, 74, 88, 64, 90]

function isPassed(element: number, index: number, array: number[]) {

return (element >= 35) }

var passed = marks.every(isPassed)

if(passed)

console.log("The student has passed.")

else

console.log("The student has failed")

//---function usaInformacao(value: number) {

console.log(value+100); }

var marks1:number[] = [58, 68, 74, 88, 64, 90]

var passA: boolean[];

marks1.forEach( n => usaInformacao(n));

// ou

// marks1.forEach(usaInformacao);

//---var numbers = [1, 4, 9];

var roots = numbers.map(n => Math.sqrt(n));

console.log("roots is : " + roots );

// ou

//var roots = numbers.map(Math.sqrt); //console.log("roots is : " + roots );

(24)

• Exercício:

1) Crie um array com notas de um aluno;

2) Filtre esse array para retornar somente as notas maiores que 60; 3) Nesse mesmo array, informe em qual posição aparece a nota 70.

Tipos básicos

Array

(25)

• Exercício - Solução:

Tipos básicos

Array

(26)

Tipos básicos

Exemplos com HTML https://www.tutorialspoint.com/typescript/typescript_arrays.htm <!DOCTYPE html> <html> <head>

<meta charset="UTF-8"> <title>

Introdução ao typescritp

</title> </head> <body>

<script type="module" src="app.js"></script> </body>

</html>

index.htm

let input = document.createElement('input');

input.setAttribute("id", "texto");

input.setAttribute("value", "Entre com o nome");

document.body.appendChild(input);

var campo: HTMLElement = document.getElementById('texto');

let button = document.createElement('button');

button.textContent = "Say Hello";

button.onclick = function() {

alert(‘Olá’);

if (campo !== null)

alert(campo.getAttribute("value")); }

(27)

• Existe uma especialização do tipo array que se chama tuple, esse tipo permite definir tipos de dados diferentes para diferentes posições do vetor:

Tipos básicos

Tupla

let tp : [string, number] = ['Jose', 10];

tp[0] = 'Tiao';

// tp[1] = 'Vieira'; <== Erro.

tp.push(100);

tp.push('Bruno');

tp.forEach((o) => console.log(o));

// tp[3] = true; <== Erro. A primeira e a segunda posição do array terão respectivamen te esses tipos. As demais posições podem assumir qualquer um dos dois

tipos (number ou string).

(28)

enum SinalSemaforo {

Verde = 1,

Amarelo = 2,

Vermelho = Verde | Amarelo

}

let sinalAtual = SinalSemaforo.Verde;

console.log(sinalAtual);

enum SinalSemaforo {

Verde = 1,

Amarelo = 2,

Vermelho= = 6

}

let sinalAtual = SinalSemaforo.Verde;

console.log(sinalAtual);

enum SinalSemaforo {

Verde,

Amarelo,

Vermelho

}

let sinalAtual = SinalSemaforo.Verde;

console.log(sinalAtual);

• Esse tipo de dado permite atribuir nomes amigáveis a valores numéricos constantes, assim temos uma lista com valores predefinidos, o uso desse tipo ajuda a melhorar a legibilidade do código.

Tipos básicos

Enum

Como não atribuímos explicitamente nenhum número aos elementos, o primeiro valor terá o numero zero, o segundo

um, e assim por diante

Fazendo a atribuição explícita de

valor.

Podemos calcular o valor, em relação aos outros

membros, nesse caso fazemos uma operação

lógica “ou” bit a bit.

sinalAtual = 2;

console.log(sinalAtual);

console.log(SinalSemaforo[sinalAtual]);

Podemos atribuir o valor inteiro diretamente. Podemos fazer a direção inversa na busca dos dados.

(29)

let notSure: any = 4;

notSure = "maybe a string instead";

console.log(notSure);

notSure = false;

console.log(notSure);

let qq: any = 10;

qq = "mudou";

console.log(qq.lenght);

let outro: Object = 10;

outro = "mudou";

console.log(outro.lenght); //<= Error: Property 'lenght' does not exist on type 'Object'.

Tipo introduzido pelo Typescript, geralmente, é utilizado quando não sabermos o

tipo do objeto referenciado por uma variável. Assim qualquer valor pode ser

atribuído a uma variável desse tipo.

Muitas vezes não podemos forçar o tipo do dado, talvez ele venha do banco ou

de uma API de terceiros. Qualquer que seja o motivo, você pode rotular sua

variável com o tipo "any", assim ela vai aceitar qualquer coisa.

Tipos básicos

Any A variável assume diferentes tipos ao longo do algoritmo.

Poderíamos pensar que Any é igual a Object, já que esse último é o tipo base de todos os elementos em Javacript, porém, os métodos disponíveis para uso são do object e não os métodos dos tipos básicos

(30)

function warnUser(): void {

console.log("This is my warning message"); }

warnUser();

• Esse tipo é utilizado para significar a ausência de tipo. Tipicamente este termo é apenas usado na declaração de funções que não devolvem qualquer valor. O uso em variáveis não é útil porque apenas permite a atribuição dos valores undefined ou null

Tipos básicos

Void

Função sem retorno

(31)

let indefinido: undefined;

indefinido = undefined;

var a;

console.log(typeof a); //resultado> "undefined"

console.log(typeof a === "object"); //resultado> false

console.log(typeof a === "undefined"); //resultado> true

console.log(typeof a == "undefined"); //resultado> true

var b = null;

console.log(typeof b); //resultado> "object"

console.log(typeof b === "undefined"); //resultado> false

console.log(typeof b === null); //resultado> true

console.log(typeof b == null); //resultado> true

• São considerados subtipos de todos os outros tipos e podem ser utilizados na declaração de variáveis. Na prática, isto significa que estes valores podem ser atribuídos a qualquer tipo de variável , não sendo seu uso isolado muito importante.

• O valor undefined significa que a variável não teve valor associado a ela, enquanto null, as variáveis, funções, propriedades e métodos nativos dos quais se espera um objeto como valor ou retorno não foram entregues/atribuídos;

Tipos básicos

Null, Undefined

Podemos declarar uma variável do tipo

indefinido, mas não faz sentido, pois ele só

receberá esse valor. Variáveis não atribuídas são undefined Objetos não atribuídos são null

function func(a: number){

if (a === undefined)

console.log('variável não definida.’); }

var x: number;

func(x);

Exemplo de uso.

(32)

function geraErro(): never{

throw new Error("erro.") }

function Principal(){

geraErro(); }

//---function infiniteLoop(): never {

while (true) { }

}

• Esse tipo representa um valor que nunca acontece. Por exemplo, pode ser usado para dizer que uma função não devolve um valor, assim não precisamos do termo return. Assim como, null e undefined, ele é considerado como um subtipo de qualquer outro tipo.

Tipos básicos

Never

Função sem retorno

Função com retorno indefinido, mas nesse

caso também vai retornar never, pois é

fruto do fluxo da execução.

function efetua(opcao: string){

if (opcao === "opc1"){

return true;

} else if (opcao === "opc2"){

return true; } geraErro(); } Outro exemplo. Apenas uma observação, void e never tem conceitos diferentes. Exemplo de uso de “never”, indicando que a função não tem

(33)

• Usamos o tipo never para indicar funções sem retorno de execução ou para indicar que a função retorna uma exceção.

Tipos básicos

Never

Função sem retorno

O type void pode receber o valor null ou undefined e o type never não pode receber nenhum valor.

E para finalizar, quando não especificado um type nas funções do TypeScript, ele retorna um valor undefined.

(34)

let outroNome = "Jhony";

outroNome = 42; // <==Erro, tipo incompatível.

• É ideal indicar explicitamente o tipo das variáveis e objetos, contudo, quando a declaração de uma variável inclui a atribuição de um valor inicial, pode-se omitir a anotação do tipo.

Tipos básicos

Inferência de tipos

Variável do tipo string.

• Existem alguns cenários nos quais o programador está em melhor posição de saber que tipo específico é referenciado por uma variável. Um exemplo é uma hierarquia de classe. Essas conversões explicitas (cast ou assertions) são feitas de duas formas:

Conversão de tipo explícita

let someValue1: any = "this is a string";

let strLength1: number = (<string>someValue1).length;

let someValue2: any = "this is a string";

let strLength2: number = (someValue2 as string).length;

let someValue3: Object = "this is a string";

let strLength3: number = (<string>someValue1).length;

let someValue4: Object = "this is a string";

(35)

function dizOla(nome: string){

return `Olá, ${nome}`; }

let imprimeMsg = function (msg: string) : void {

console.log(msg); }

imprimeMsg(”teste!!”);

• Funções desempenham um papel importante em Typescript.

Funções

Funções nomeadas e anônimas

Função nomeada em que espera um valor string e retorna também um string. A linguagem aceita funções anônimas, para sua execução temos que associa-la a alguma variável.

(function() {console.log('anonima 1')})();

(function(a: number, b: number) {console.log(a+b)})(10,15);

Uma outra forma de execução é transformando a

função em uma expressão com os parênteses “()”.

O segundo par de parêntese indica o local para passar os parâmetros da função.

(36)

let impressora : (nome: string) => void;

impressora = function(info: string){

console.log(info); }

impressora("testando...");

• Funções podem ser usadas para definir novos tipos que, por sua vez, são utilizadas para tipificar outras variáveis ou parâmetros..

Funções

Especificação de tipo função

Definindo um tipo: Impressora é uma variável que espera uma referencia

para uma função que recebe uma string e não retorna valor.

Aqui temos a referencia para o

tipo de retorno.

Iniciando a variável com uma função válida para seu tipo.

Executa a função anônima sobre a variável impressora

var res = function (a: number, b: number) {

return a * b; };

console.log(res(12, 2));

Outro exemplo de função anônima.

(37)

function opcionais(nome: string, idade?: number){

if (idade == undefined)

console.log(`Olá ${nome}`);

else

console.log(`Olá ${nome}, você tem ${idade} anos.`); }

opcionais("Tião",22);

opcionais("Maria");

• Por padrão todos os parâmetros de uma função em Typescript são obrigatórios.

Contudo, podemos criar parâmetros opcionais utilizando o ponto de interrogação (?).

Funções

Parâmetros opcionais

Atenção: uma função pode definir vários parâmetros opcionais, devendo estes serem sempre colocados depois

dos parâmetros obrigatórios, se existirem. Marcamos o parâmetro como opcional. Chamada com dois e com um parâmetro.

(38)

function predefinidos (nome: string = "Raul", idade = 20){

console.log(`Nome: ${nome}, idade ${idade}`); }

predefinidos();

• Se for necessário, podemos atribuir um valor padrão para um parâmetro, Nesses casos, esse valor é utilizado no interior da função quando não atribuímos explicitamente um valor para parâmetro.

Funções

Parâmetros com valores predefinidos

Definindo valor padrão para os dois

parâmetros. Atenção: uma função pode definir

vários parâmetros com valores padrões, devendo estes serem sempre colocados depois dos parâmetros sem

(39)

function restParams(nome: string, ...outros:string[]){

return `Nome: ${nome} \n ${outros.join(' ')}`; }

console.log(restParams("Joe", "John", "Gilbert"));

console.log(restParams("Mary"));

function addNumbers(...nums:number[]) {

var i: number;

var sum:number = 0;

for(i = 0;i<nums.length;i++) {

sum = sum + nums[i]; }

console.log("sum of the numbers",sum) }

addNumbers(1,2,3)

addNumbers(10,10,10,10,10);

• A linguagem permite criar funções que esperam zero ou mais parâmetros de um determinado tipo. Esses parâmetros são chamados rest.

• Os parâmetros deste tipo são sempre representados por um array, para sua declaração temos que usar o caractere (...). Esse tipo de parâmetro tem que ser declarado no final da lista de variáveis.

Funções

Parâmetros REST

O programador pode optar por passar nenhum

parâmetro. Uso de parâmetro rest.

“join” cria ums string a partir de

(40)

let numeros = [1,2,3,4,5];

let aux1 = numeros.filter( function (valor, index, arr) {

return valor % 2 === 0} );

console.log(aux1.join(' '));

let aux2 = numeros.filter( (valor, index, arr) => valor % 2 === 0);

console.log(aux1.join(' '));

var foo1 = (x: number) => 10 + x

console.log(foo1(100))

var foo2 = function (x: number) { return 10 + x; };

console.log(foo2(100));

• Esse tipo de função é utilizado para facilitar a escrita de funções anônimas, ela é composta pela seção de parâmetros, o operador lambda (=>) e seu bloco de código (estrutura).

Funções

Funções arrows ou lambdas

Agora utilizamos o método filter do array passando uma função como

parâmetro. O primeiro exemplo mostra a forma convencional e o segundo usando funções arrow. Exemplo de criação e uso

de funções arrow. Logo abaixo, vemos a criação do

mesmo código sem o uso de funções lambdas.

var display = x => {

console.log("The function got "+x) }

display(12);

O uso do parêntese é opcional quando temos

(41)

• Exercício:

1) Crie uma função que recebe uma string e retorne a string com os caracteres separados por hífen. Exemplo: “Jose” => “J-o-s-e”;

2) Crie uma função que recebe uma string e retorna se ela é palindromo;

3) Crie uma função que recebe um array de string, retorne um array indicando se cada palavra é palindromo.

Tipos básicos

Funções

(42)

• Exercício - Respostas: 1)

2)

Tipos básicos

Funções

let soletrar = function (x: string): string{

x = x.replace("-","");

x = x.replace(" ","");

return x.toUpperCase().split("").join("-"); }

console.log(soletrar("Bruno Ferreira"));

console.log(soletrar("guarda-chuva"));

function isPalindromo(l) {

let x = l.split("").reverse().join("");

return (x == l) ? true : false; }

console.log(isPalindromo('casa'));

console.log(isPalindromo('oborobo'));

console.log(isPalindromo('asa'));

console.log(isPalindromo('babab'));

console.log(isPalindromo('Frango'));

Primeiro com a função split(), transformei um string em uma array, tendo uma array eu posso utilizar a função reverse(), que inverte a ordem dos elementos de uma array e por último utilizei a função join(), que junta os elementos de uma array em uma string.

(43)

Operador Descrição

+ Operador binário. Retorna a soma de dois números.

- Operador binário. Retorna a subtração de dois números.

* Operador binário. Retorna a multiplicação de dois números.

/ Operador binário. Retorna a divisão de dois números.

++ Operador unário. Adiciona um ao seu operando. Se usado como operador

prefixado (++x), retorna o valor de seu operando após a adição. Se usado como operador pós fixado (x++), retorna o valor de seu operando antes da adição.

-- Operador unário. Subtrai um de seu operando. O valor de retorno é análogo

àquele do operador de incremento.

% Operador binário. Retorna o inteiro restante da divisão dos dois operandos.

• Operadores aritméticos tomam valores numéricos (sejam literais ou variáveis) como seus operandos e retornam um único valor numérico.

Operadores

(44)

Operador Descrição

&& Operador retorna verdadeiro somente se toda a expressão for verdade.

|| Operador retorna verdadeiro somente se pelo menos uma expressão for

verdade.

! Operador retorna o inverso do valor inicial de uma expressão.

& Operador que executa uma operação bolleana do tipo (and) em cada bit dos

operandos informados.

| Operador que executa uma operação bolleana do tipo (or) em cada bit dos

operandos informados.

^ Operador que executa uma operação bolleana do tipo (Xor – ou excluisvo) em

cada bit dos operandos informados.

~ Operador que executa uma operação bolleana do tipo (not) em cada bit dos

operandos informados.

• Operadores lógicos são utilizados tipicamente com valores booleanos (lógicos); neste caso, retornam um valor booleano.

Operadores

(45)

Operador Descrição

= Operador de atribuição. Associa o valor da direita ao operando do lado

esquerdo.

+= Adiciona o valor do operando da direta com o da esquerda e atribui o resultado

no operando do lado esquerdo.

-= Subtrai o valor do operando da direta com o da esquerda e atribui o resultado

no operando do lado esquerdo.

*= Multiplica o valor do operando da direta com o da esquerda e atribui o

resultado no operando do lado esquerdo.

/= Adiciona o valor do operando da direta com o da esquerda e atribui o resultado

no operando do lado esquerdo.

• Um operador de atribuição atribui um valor ao operando à sua esquerda baseado no valor do operando à direita. O operador de atribuição básico é o igual (=).

Operadores

(46)

Operador Descrição

> Maior que (operando da esquerda é maior que o operador da direita).

< Menor que (operando da esquerda é menor que o operador da direita.

>= Maior ou igual a (operando da esquerda é maior ou igual ao operador da direita.

<= Menor ou igual a (operando da esquerda é menor ou igual ao operador da direita.

== Retorna verdadeiro caso os operandos tenham valores iguais.

!= Retorna verdadeiro caso os operandos não tenham valores iguais.

=== Retorna verdadeiro caso os operandos tenham valores e tipo iguais.

!== Retorna verdadeiro caso os operandos tenham valores ou tipos diferente.

• Um operador relacional compara seus operandos e retorna um valor lógico baseado em se a comparação é verdadeira.

Operadores

Relacionais Operadores aplicados ao Javascrip puro.

(47)

• Alguns exemplos...

Operadores

(48)

• Interfaces permitem definir tipos que podem ser utilizados pelo compilador Typescript na validação do código, esse conceito define a estrutura do objeto;

• Interface pode ser vista como um contrato, ou seja, o formato de um novo tipo, caso uma declaração não esteja de acordo com a interface, um erro é lançado pelo

compilador.

• Como Javascript não tem suporte a esse recurso a definição da interface é ignorado quando o código é transcrito.

• Uma interface define uma coleção de propriedades e métodos, sem especificar os

detalhes de implementação associados a cada um desses membros. Esses detalhes são obrigação de um objeto ou uma classe que venha implementar a interface em questão. • Se um objeto ou classe que possuem os mesmos nomes, lista de parâmetros e tipos de

retorno que uma interface, então dizemos que são compatíveis.

Interface

(49)

• Para criar uma estrutura desse tipo, utilizamos a palavra reservada interface. Seguido pelo nome, sendo os seus membros definidos no interior de um bloco delimitado por chaves.

Interface

Sintaxe interface Pessoa { nome: String; imprime: () => void; }

Para que algum tipo seja compatível com essa interface

ela tem que ter o mesmo atributo e

método.

function imprime(p: Pessoa){

if (!p.nome){

p.nome = 'Sem nome'; }

p.imprime(); }

Qualquer variável que tem a estrutura da interface poderá ser passada como

parâmetro nessa função.

(50)

interface LabelledValue {

label: string; }

function printLabel2(labelledObj: LabelledValue) {

console.log(labelledObj.label); }

let myObj2 = {size: 10, label: "Size 10 Object"};

printLabel2(myObj2);

function printLabel1(labelledObj: { label: string }) {

console.log(labelledObj.label); }

let myObj1 = {size: 10, label: "Size 10 Object"};

printLabel1(myObj1);

• Exemplo

Interface

Sintaxe

Uma alternativa ao uso de interface é declarar o

parâmetro como um objeto, nesse caso, todo

objeto que tenha a propriedade label do tipo

string pode ser passado como parâmetro.

Agora o mesmo exemplo é implementado com o uso

de interface, apesar de termos um código com mais linhas, a legibilidade

com o uso de interface é indiscutível.

(51)

interface SquareConfig {

color?: string;

width?: number; }

function createSquare(config: SquareConfig): { color: string; area: number } {

// ...

return null; }

let mySquare = createSquare({ colour: "red", width: 100 });

• Evitando erros

Interface

Sintaxe

Nesse exemplo, ocorreu um erro de digitação ao criar o object literal, em Javascript esse

erro seria imperceptível e ocorreria apenas em tempo de

execução. Mas com o uso de interface, o problema é apontado imediatamente.

(52)

function imprimir(p: OutraPessoa){

if (!p.nome){

p.nome = 'Sem nome'; }

if (p.imprime){

p.imprime(); } else {

console.log (`Sem membro imprime: ${p.nome}`); }

}

• Se for necessário, pode-se deixar um membro da interface como opcional através do caractere “?”.

Interface

Membros opcionais

Qualquer objeto que apresente uma

propriedade designada por “nome” é considerada compatível. Membros opcionais obriga-nos a ter algum cuidado na interação com objetos compatíveis. interface OutraPessoa { nome: String; imprime?: () => void; }

(53)

interface AlunoInterno{

readonly nome: string; }

let aluno: AlunoInterno = {nome: 'Jimy'};

aluno.nome = 'Jhon’; // Erro de compilação

• A linguagem suporta a criação de membros cujo os valores só podem ser alterados

durante a criação dos objetos que são compatíveis com a interface. Para isso, basta usar a palavra reservada readonly.

Interface

Membros somente leitura

Informando que o campo é somente leitura. Podemos atribuir o valor ao membro “nome” somente uma vez, a linha de baixo resultaria em

(54)

interface Pessoa {

nome: String;

imprime: () => void; }

interface Aluno extends Pessoa{

turma: string; }

• A linguagem suporta que uma interface estenda outra. Para isso tem-se que recorrer a palavra reservada extends.

Interface

Herança de interfaces

Uma variável que pertence ao tipo Aluno

terá as propriedades nome e turma, além do

método opcional “imprime” Uma interface pode herdar membros de várias outras interfaces usando a virgula (,) para declará-la.

(55)

• Primeiro vamos entender o que são objetos literais.

• Agora podemos analisar os erros de compatibilidades da linguagem entre literais e interfaces

interface Atendente{

nome: string; }

function imprimeNome(user: Atendente){

console.log(user.nome); }

imprimeNome({nome: 'Luiz', endereco: 'Rua 23’}); //  Erro

var u: Atendente = {nome: 'Luiz', endereco: 'Rua 23’}; //  Erro

var at1 = {nome: 'Luiz', endereco: 'Rua 23'};

imprimeNome(at1);

var u: Atendente = {nome: 'Luiz', endereco: 'Rua 23'} as Atendente;

var carro = {

marca: "Ford",

modelo: "Ka",

getDetalhes: function () {

return this.marca + ' - ' + this.modelo; }

}

Interface

Compatibilidade de interfaces com objetos literais

Como mecanismo de segurança, a atribuição de objetos literais diretamente a

parâmetros do tipo de uma interface, só é permitida se esse objeto definir apenas propriedades compatíveis com as da interface. Nesse exemplo a propriedade “endereço” não

existe na interface.

Literais são maneiras menores para definir objetos. Basta inserir entre chaves as propriedades e métodos de

um objeto. Nesse caso o objeto já é instanciado e referenciado pelo nome

da variável que ele foi atribuído.

Para burlar esse mecanismo de segurança, pode-se

usar uma variável auxiliar ou fazer uma

(56)

interface Existe{

(nome:string): boolean; }

let nomes = ['Rui','Jhon','Jimmy','Robert','Fancisca’];

let pesquisa: Existe = (n) => nomes.indexOf(n) >= 0;

console.log(pesquisa('Robert'));

console.log(pesquisa('Maria'));

• Vimos que interfaces descrevem a forma de objetos, Sendo as funções um objeto em Typescript, pode-se também definir funções através de uma interface.

Interface

Funções

2) Tipificamos uma variável que agora espera

uma função que é responsável por indicar

se um nome está presente em um array.

1) Nesse caso, a interface contém a assinatura do método

desejado. Nesse caso, uma função deve receber uma string

e retornar um boolean;

3) Ao definir a função, podemos usar outros nomes

para os parâmetros e não precisamos definir o tipo, pois

o compilador usa o tipo declarado na interface.

(57)

class Pessoa{

nome: String;

constructor(nome: string){

this.nome = nome; }

dizOla(){ console.log(`Olá ${this.nome}`)}; }

let n1 = new Pessoa('Tião');

• Javascript não tem suporte completo a orientação a objetos, na verdade a linguagem emula o conceito através de protótipo e das chamadas funções construtoras.

• A partir da ECMAScript 2015 foram introduzidos novos termos para que o código fique semelhante aos de linguagens tradicionalmente orientadas a objetos como C# e Java. • Typescript implementa as melhorias da nova versão de Javascript adicionando mais

recursos similares a linguagens OO e converte seus termos em código válido.

Classes

Introdução

1) Nome da classe

2) Definimos um construtor.

3) A classe tem uma propriedade e um método.

(58)

let m3: Pessoa = new Pessoa2('Robert');

class Pessoa{

public nome: String;

public constructor(nome: string){

this.nome = nome; }

public dizOla(){ console.log(`Olá ${this.nome}`)}; } 1) Podemos explicitar a visibilidade, mesmo que o padrão é public. class Pessoa2{

private nome: String;

constructor(nome: string){

this.nome = nome; }

dizOla(){ console.log(`Olá ${this.nome}`)}; }

let n2 = new Pessoa2('Tião');

n2.nome = 'teste'; // <- Erro.

• Por padrão todos os membros de uma classe são públicos. Mas ao contrário do Javascript, o Typescript suporta o uso de outros níveis de visibilidade.

Classes

Visibilidade

2) Esse membro só pode ser acessado dentro da classe.

3) Dois objetos são compatíveis quando os tipos, nomes e visibilidade das propriedades são os mesmo. Nesse caso, o

(59)

class Mamiferos{

constructor(private nome: string){ }

imprimirNome(){

console.log(`Olá ${this.nome}`) };

}

let gato = new Mamiferos('Chaninho.’);

gato.imprimirNome;

1) A classe tem a propriedade “nome”

que é privada.

• Existe um atalho que reduz o código necessário para declarar propriedades. Quando os parâmetros de um construtor tem anotados também os qualificadores, o compilador Typescrip injeta campos na classe com os mesmos nomes e qualificadores desses parâmetros.

Classes

(60)

class Aves{

private _nome: string;

constructor(nome: string){ this._nome = nome; }

get nome(){

return this._nome; }

set nome(nome: string){

if (!nome)

console.error('Erro. nome obrigatório’);

else

this._nome = nome; }

imprimirNome(){ console.log(`Olá ${this._nome}`)}; }

let ave = new Aves('Galinha');

ave.imprimirNome();

ave.nome = 'Faizão';

ave.imprimirNome();

1) Deve-se acessar as propriedades pelos nomes dos métodos.

Mas as métodos são acessados como

propriedades.

• As propriedades podem ser vistas como campos onde o acesso de leitura ou escrita é feito através do uso de métodos especiais.

Classes

Getters e Setters

1) Esses métodos acessam a propriedade _nome,

eles são uteis para proteger as variáveis

de atribuições incorretas.

(61)

class MembrosOpcionais{

nome: string;

idade?: number;

imprimeIdade?(): string; }

var mOp = new MembrosOpcionais();

if (mOp.imprimeIdade)

console.log(mOp.imprimeIdade)

2) Os membros opcionais podem retornar o tipo undefined, sendo assim, temos

que fazer o teste antes do uso dos métodos opcionais.

• Assim como as interfaces, os membros de uma classe podem ser opcionais, para isso usamos o caractere “?”.

Classes

Membros opcionais

1) O campo idade e o método são opcionais.

Como o método é opcional não precisa de

(62)

class Grid{

static Origem = {x: 0, y:0};

calculaDistancia(ponto: {x: number, y:number}){

let xD = (ponto.x - Grid.Origem.x);

let yD = (ponto.y - Grid.Origem.y);

return Math.sqrt(xD * xD + yD * yD); }

constructor (public escala: number){}; }

let distancia = new Grid(1).calculaDistancia({x:11, y:11});

console.log(distancia);

console.log(Grid.Origem.x);

2) Utilizamos o membro estático para calculo da distância, repare que o uso é feito através do nome da classe.

• Membros estáticos são compartilhados entre todas as instâncias criadas a partir de uma classe e acessadas através do nome da classe.

Classes

Membros estáticos 1) Declaramos um membro estático. 3) Mais um exemplo de uso de um membro estático.

(63)

class Aluno extends Pessoa{

private _idade: number;

constructor(nome: string, idade: number){

super(nome);

this._idade = i; };

get idade(){

return this._idade; }

set idade(valor: number){

this.idade = valor; }

}

let aluno1 = new Aluno('Johny', 23);

aluno1.nome = 'Johny Lemos';

2) A classe é obrigado a invocar o construtor da classe pai através da palavra super.

• Técnica utilizada para obter reutilização de código e implementar o conceito de polimorfismo. Segue os mesmos padrões de linguagens OO e usa a palavra reserva

extends para a herança de código.

Classes

Herança 1) Herdamos os membros da classe Pessoa. 3) Podemos acessar os métodos públicos herdados pela classe.

4) Seguindo os conceitos da OO clássica, pode-se declarar membros com encapsulamento

protected. Esse nível de acesso restringe a utilização dos membros somente à classe ou

(64)

abstract class Base{

nome: string;

abstract dizOla(); }

class Derivada extends Base{

dizOla(){

console.log('Ola!!!’); }

}

let derivada = new Derivada();

derivada.dizOla();

• Como na orientação a objetos clássica, em Typescript pode-se criar classes que não podem ser instanciadas diretamente. Essas classes servem apenas de padrão para as classes filhas, esse comportamento é alcançado através da palavra reservada abstract.

Classes

Classes abstratas 1) Não podemos instanciar objetos da classe abstrata. 3) Implementação do método abstrato. 2) Método que deve ser implementando pelas classes filhas.

(65)

class Ponto{

x: number;

y: number; }

interface Ponto3d extends Ponto{

z: number; }

function imprimePonto(p: Ponto3d){

console.log(`Ponto x: ${p.x}, y ${p.y}, z ${p.z}`); }

let pTeste: Ponto3d = {x: 1, y: 2, z: 3};

pTeste.x = 10;

pTeste.y = 20;

pTeste.z = 30;

imprimePonto(pTeste);

• Comportamento que não é comum as linguagens OO tradicionais, as classes em

Typescript pode servir como tipo base de uma interface, parecido com uma herança. Ou seja, a interface herda os membros da classe.

Classes

Classes usadas como interface

1) A interface herda apenas a forma dos membros, ou seja, se a classe tiver algum método, a interface herda somente a assinatura do método, não a sua implementação.

2Acessando os três membros da

interface. Sendo que x e y foram

(66)

function padLeft(value: string, padding: string|number) {

if (typeof padding === "number") {

return Array(padding + 1).join(" ") + value; }

if (typeof padding === "string") {

return padding + value; }

throw new Error(`Esperando string ou número: '${padding}'.`); }

let r = padLeft('Texto..',4);

console.log(r);

r = padLeft('Texto..','Inicio');

console.log(r);

• Typescript permite que um parâmetro ou uma variável assuma mais de um tipo. Esse conceito é chamado de união de tipos (“|”).

Outros tipo

Unions

1) Usamos o conceito de união para definir que o parâmetro poderá ser do

tipo string ou number.

2) Usamos a função com os

dois tipos de parâmetros.

3) O tipo “any” poderia ter sido usado, contudo, o usuário tem a possibilidade

de usar um tipo boolean, o que não é o desejado.

(67)

interface Bird { raca: string; fly(); layEggs(); } interface Fish { raca: string; swim(); layEggs(); }

function getSmallPet(): Fish | Bird {

let f: Fish;

return f; }

let pet = getSmallPet();

pet.layEggs(); // Correto

pet.swim(); // Erro

class Cliente {

endereco: string;

constructor(public nome: string){} }

class Fornecedor {

telefone: string;

constructor(public nome: string){} }

let x1: Cliente|Fornecedor;

x1 = new Cliente('Jorge');

x1.endereco = 'Rua do centro';

console.log(x1.endereco);

x1 = new Fornecedor('Farmácia');

x1.telefone = '2222-2222';

console.log(x1.telefone);

Outros tipo

Unions

1) Quando recorremos a uma união para definir o tipo de um objeto, o compilador só permite o uso de membros comum

ao tipo instanciado.

2) Quando recorremos a valores que tem o tipo união, somente os

membros em comum dos tipos podem ser

(68)

let aa: number = 9;

console.log(typeof aa); // "mumber"

console.log(typeof {}); // "object"

console.log(typeof []); // "object"

console.log(typeof new Date()); // "object"

console.log(typeof new RegExp('')); // "object"

console.log(typeof null); // "object"

Outros tipo

Guardas

1) Não descobrimos qual a classe do objeto, somos informados apenas que é

um objeto.

• Em Javascript é normal verificar se a variável é de um determinado tipo. Isso é necessário, pois as variáveis podem ser uniões de tipo. Para isso temos as palavras reservadas typeof, instanceof e in.

• O operador typeof trabalha em um variável e retorna uma string, indicando o tipo do valor.

• O operador typeof é excelente para reconhecimento de valores primitivos, como os acima citados. Para detecção de valores de referência, entretanto, eles não possuem serventia:

•Para strings, typeof retorna“string.” •Para numbers, typeof retorna“number.” •Para booleans, typeof retorna“boolean.” •Para undefined, typeof retorna“undefined.”

(69)

Outros tipo

Guardas

• O operador instanceof distingue instâncias de classes diferentes.

• Ainda temos o operador in para verificar se existe algum determinado membro em um objeto:

console.log({} instanceof Object); // "object"

console.log([] instanceof Array); // "object"

console.log( new Date() instanceof Date); // "object"

console.log(new RegExp('') instanceof RegExp); // "object"

interface Point {

x: number;

y: number;}

interface Point3d extends Point {

z: number;}

function plot(point: Point) {

if ('z' in point) { // point é um `Point3D` } else { // point é um `Point` } }

(70)

interface Square { kind: "square"; size: number; } interface Rectangle { kind: "rectangle"; width: number; height: number; } interface Circle { kind: "circle"; radius: number; }

function area(s: Square | Rectangle | Circle) {

switch (s.kind) {

case "square": return s.size * s.size;

case "rectangle": return s.height * s.width;

case "circle": return Math.PI * s.radius ** 2; }

}

let forma: Circle = {kind: "circle", radius: 3.15};

console.log( area(forma) );

Outros tipo

Discriminated unions ou tagged Unions

• Existe um outro recurso de guarda, o qual consiste em criar um campo em comum entre os tipos, assim o compilador é capaz de inferir o tipo de acordo com esse campo em uma condição if ou switch.

(71)

interface IPessoa{ nome: string; } interface IAluno{ escola: string; }

function imprimeInfo( estudante : IPessoa & IAluno){

console.log( `${estudante.nome} matriculado na escola

${estudante.escola}` ); }

let jorge = {nome: 'Jorge Silva', escola: 'Militar'};

imprimeInfo(jorge);

Outros tipo

Interseções de tipos

• As interseções (&) são tipos personalizados criados a partir da combinação de vários tipos. Assim, o objeto assume simultaneamente a identidade de todos os tipos e será

(72)

Outros tipo

Aliases

• Aliases permite criar nomes alternativos para tipos existentes. Não se trata de um novo tipo, mas são uteis para a redução de código e para melhorar a abstração dos problemas. Pode-se renomear tipos primitivos, uniões, tuplas, entre outros tipos criados pelo usuário.

type Nome = string;

type NomeCorreto = () => string;

type NomeOrNomeCorreto = Nome | NomeCorreto;

function getName(n: NomeOrNomeCorreto): Nome {

if (typeof n === "string") { return n; } else return n(); } type Tree = { value: number; left: Tree; right: Tree; }

type Matriculado = IPessoa & IAluno;

function imprimeNovo( estudante : Matriculado){

console.log( `${estudante.nome} matriculado na escola ${estudante.escola}` ); }

1) Usamos a palavra reservada typepara criar os apelidos. Podemos criar

apelidos utilizando outros apelidos e dar apelidos

(73)

Outros tipo

String literal Types

• String literal types permitem criar um novo tipo de dados em que o tipo string recebe exatamente os valores que foram especificados na definição.

let resposta: "Sim" | "Não";

resposta = "Sim";

//resposta = "talvez"; <===Erro

type Easing = "ease-in" | "ease-out" | "ease-in-out";

class UIElement {

animate(dx: number, dy: number, easing: Easing) {

if (easing === "ease-in") {

// ...

}

else if (easing === "ease-out") { }

else if (easing === "ease-in-out") { }

else {

// error! should not pass null or undefined.

} } }

let button = new UIElement();

button.animate(0, 0, "ease-in");

(74)

Outros tipo

Iteradores

• Typescript implementou os conceitos de iterable e iterator. Se o objeto devolver um iterator a partir de uma propriedade que referencia uma função acessada pelo símbolo Symbol.iterator, ele passa a ser um iterable.

• Vários dos tipos introduzidos pela linguagem (ex.: Array, Map, Set, String) são iterables. • A forma mais fácil de iterar sobre essas coleções é através das instruções for..of e for..in

let list = [4, 5, 6];

for (let i in list) {

console.log(i); // "0", "1", "2",

}

for (let i of list) {

console.log(i); // "4", "5", "6"

}

let iterar = {nome: 'Bruno’,

sobrenome: 'Ferreira'};

for (let i in iterar) {

console.log(i); }

for (let i of iterar) {

console.log(i); }

for..of for..in

Acessa o valor Acessa a chave que retorna o valor Aplicado somente a objetos iterables Pode ser aplicado a qualquer objeto Percorre o objeto sem conhecer a forma Percorre o objeto sem conhecer a forma

1) O primeiro laço retorna os índices, o

segundo os valores desses índices.

2) O primeiro laço retorna o nome das

propriedades, o segundo mostra um erro de compilação, pois o objeto não é

(75)

class Flies {

fly() {

console.log('voando...'); }

}

class Climbs {

climb() {

console.log(‘subindo na parede'); }

}

Outros tipo

Mixim ou herança múltiplas

• Typescript permite a criação de classes a partir da combinação de outras. Fornecendo assim herança múltipla. Tem-se que seguir três passos para obter o resultado esperado:

1. Utilizar a palavra implements ao invés de extends durante a composição da nova classe;

2. Redeclarar as propriedades e os métodos como propriedades na nova classe.

3. Criar um método chamada applyMixins com os argumentos corretos.

1) Começamos com duas classes simples que representam superpoderes de

(76)

class BeetleGuy implements Climbs, Flies { climb: () => void; fly: () => void; sting(){ this.fly(); this.climb();

console.log('ferroa!!'); }

}

function applyMixins(derivedCtor: any, baseCtors: any[]) {

baseCtors.forEach(baseCtor => {

Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {

if (name !== 'constructor') {

derivedCtor.prototype[name] = baseCtor.prototype[name]; }

}); });

}

applyMixins (BeetleGuy, [Climbs, Flies]);

let superBesouro = new BeetleGuy();

superBesouro.sting();

Outros tipo

Mixim ou herança múltiplas

2) Criamos uma terceira classe que herda os poderes das duas primeiras classes (herança múltipla), para qual usamos a

palavra chave implements.

3) Redeclaramos todos os métodos como propriedades,

nesse caso, não existiam

propriedades a serem herdadas. 4) Criamos o seguinte método

para que o compilador consiga fazer a transcrição da herança múltipla para o Javascript. Esse método pode ser criado e inserido

em um módulo para ser aplicado quando necessário.

5) Registramos a classe com herança múltipla utilizando o

método criado e, por fim, utilizamos a nova classe instanciando um objeto.

(77)

function compara<T>(parametro1: T, parametro2: T): boolean{

return parametro1 == parametro2; }

console.log(compara<number>(10,20));

console.log(compara<string>('bh','sp’));

console.log(compara(true,true));

Outros tipo

Generics

• Typescript, como outras linguagens oferece o recurso de generics, o qual visa aumentar a

reusabilidade de código tornando os tipos de dados genéricos, isso sem perder a verificação de tipos.

• Um exemplo clássico é o uso de coleções que são capazes de se adaptarem a diferentes tipos de objetos ou tipos primitivos.

• Veja um exemplo abaixo, aonde não queremos usar o tipo any, para dar mais segurança referente os tipos de dados a uma função que compara se os valores são iguais:

1) Introduzimos um ou mais parâmetro de tipos, de qualquer nome (padrão T) que serve

como um placeholder para tipos concretos.

2) Definimos o tipo da função quando ela é invocada. 3) Se omitirmos o placeholder, o compilador tentará inferir o tipo.

(78)

interface Molde { <T>(arg: T): T; }

function identidade<T>(arg: T): T {

return arg; }

let myIdentity: Molde = identidade;

console.log(myIdentity<number>(1000));

function identity<T>(arg: T): T {

return arg; }

let myIdentity: <U>(arg: U) => U = identity;

console.log(myIdentity(3000));

Outros tipo

Generics

• Pode-se usar diferentes nomes para os parâmetros de tipos genéricos:

• Pode-se utilizar generics em funções de uma interface, isso pode ser feito de duas formas: 1) Usamos o nome “T” para a definição da função e o nome “Q” para a definição de um tipo que irá receber a função, o qual mantém

a mesma assinatura da função identity.

2) Declaramos o tipo genérico na função da interface. 3) Se omitirmos o placeholder, o compilador tentará inferir o tipo. interface Molde<T> { (arg: T): T; }

function identidade<T>(arg: T): T {

return arg; }

let myIdentity: Molde<number> = identidade;

console.log(myIdentity(1000));

2) Declaramos o tipo genérico na definição da

(79)

class Generica<U>{

constructor(public t: U){} }

let g = new Generica<boolean>(true);

console.log(g.t);

class AdicionaGenerico<T> {

valorInicial: T;

add: (x: T, y: T) => T; }

let myGenericNumber = new AdicionaGenerico<number>();

myGenericNumber.valorInicial = 0;

myGenericNumber.add = function(x, y) { return x + y; };

console.log(myGenericNumber.add(100,400));

let stringNumeric = new AdicionaGenerico<string>();

stringNumeric.valorInicial = " ";

stringNumeric.add = function(x, y) { return x + y; };

console.log(stringNumeric.add(stringNumeric.valorInicial, "test"));

• Pode-se utilizar generics em classes, isso pode ser feito da seguinte forma:

• Outro exemplo:

Outros tipo

Generics 1) Classe com o tipo genérico definido na declaração da classe. 2) Instanciamos dois objetos com

tipos diferentes.

3) Propriedade definida com

generics no construtor

(80)

• O compilador Typescript, em muitas das vezes, não consegue prever se um parâmetro do tipo genérico tem uma determinada propriedade ou método. Veja o exemplo abaixo:

• Contudo, temos que garantir que o tipo passada terá esse método ou propriedade e isso é feito criando uma interface (contrato) em conjunto com a palavra reservada extends durante a

declaração do tipo genérico:

function registrar<T>(arg: T): T {

console.log(arg.length);

return arg; }

Outros tipo

Generics Constraints

1) Essa linha apresenta um erro, o compilador não reconhece o método lenght

interface Comprimento {

length: number; }

function registrar<T extends Comprimento>(arg: T): T {

console.log(arg.length);

return arg; }

(81)

• Outro exemplo:

• Podemos aprofundar nos exemplos criando restrições entre os parâmetros de tipo genéricos:

function getProperty<T, K extends keyof T>(obj: T, key: K) {

return obj[key]; }

let xs = { a: 1, b: 2, c: 3, d: 4 };

let retorno = getProperty(xs, 'a'); // okay

console.log(retorno);

//retorno = getProperty(xs, 'm'); //Erro: não existe a chave 'm' //console.log(retorno);

Outros tipo

Generics Constraints

2) O tipo k têm os mesmos membros que o elemento T.

interface PropriedadeNome{

nome:string; }

class PessoaFisica{

constructor(public nome: string){} }

class PessoaJuridica{

constructor(public nome: string){} }

function envia<Y extends PropriedadeNome>(obj:Y){

console.log('get:http:\\\\localhost\\8080\\'+obj.nome); }

envia({nome: 'matriz'});

1) O tipo Y tem a propriedade nome.

(82)

• Promise é um tipo de dado que tenta solucionar problemas relacionados com tarefas assíncronas em cadeia.

• Esse tipo de dado é responsável por notificar acerca da sua conclusão. Sua especificação é direta

• Promises aceitam uma função por parâmetro. Esta função será executada recebendo duas novas funções em seus argumentos – uma para resolver a promise, outra para rejeitá-la. Caso um erro aconteça dentro de uma promise, ela também será rejeitada.

• Uma promise possui dois métodos principais:

then: Executado quando a promise é resolvida; catch: Executado em caso de rejeição (ou throw).

Outros tipo

Tipo Promises

let pr = new Promise ( (resolve, reject) => {

// resolva ou rejeite

(83)

• Exemplo 1:

• Tanto a função resolve quanto a reject podem ser executadas apenas uma vez dentro de uma promise.

• Já o método then pode ser usado várias vezes para a mesma promise.

Outros tipo

Tipo Promises

let pr = new Promise ( (resolve, reject) => {

resolve(10); });

pr.then(valor => console.log(value));

1) Nome padrão das funções para aceitar e

rejeitar a promessa.

2) Quando executarmos a promessa, ela dirá que o processamento foi resolvido e

o valor final é 10.

2) O método then é acionado com a promessa resolvida. A

variável “valor” recupera o retorno da promessa.

let pr2 = new Promise ( function (resolve, reject) {

resolve(100); });

pr2.then( (valor) => {console.log(valor); return 200;}) .then( (v) => console.log(v))

.catch( (err) => console.log('erro!'));

4) Caso o método reject tivesse sido acionado dentro da

promise, o catch seria executado.

(84)

function abrirArquivo() : Promise<String>{

return new Promise( (resolve,reject) => {

//abrindo o arquivo...

let correto = true;

if (correto)

resolve("Aberto..")

reject("erro ao abrir o arquivo.") });

}

function lerArquivo() : Promise<String>{

return new Promise( (resolve,reject) => {

//abrindo o arquivo...

let correto = false;

if (correto)

resolve("Lendo..")

reject("erro ao ler o arquivo.") });

}

function fecharArquivo() : Promise<String>{

return new Promise( (resolve,reject) => {

//abrindo o arquivo...

let correto = true;

if (correto)

resolve("Fechando..")

reject("erro ao fechar o arquivo.") });

}

abrirArquivo()

.then( () => lerArquivo()

.then( () => fecharArquivo()

.then( () => console.log('tudo certo!'))

.catch( (errFechar) => console.log(errFechar)) .catch( (errLer) => console.log(errLer) ) ) )

.catch( (errAbrrir) => console.log(errAbrrir));

• Exemplo 2:

Outros tipo

Tipo Promises 1) Geralmente usamos

Promise como retorno de funções.

2) Uma das grandes vantagens de Promise é que podemos encadear ações em ambientes

assíncronos. Contudo, simulamos uma ação de três passos que é o de abrir, ler e

(85)

• all: retorna uma promise pendente que será resolvida quando todas as promises passadas por parâmetro (array) forem resolvidas. Ela será rejeitada se qualquer uma das promises rejeitar. • race: retorna uma promise pendente, mas ela será resolvida assim que qualquer uma das

promises enviadas seja resolvida, se uma delas falhar antes de qualquer uma ser resolvida, então essa promise será rejeitada.

Outros tipo

(86)

• A modularização é um importante conceito para a organização do código fonte, melhorando a legibilidade e consequentemente a manutenção dos sistemas, a partir da ECMAScript 2015 o Typescript passou a dar suporte a esse conceito;

• O problema é que o conceito foi introduzido recentemente então a comunidade Javascript resolvia essa ausência propondo soluções diferentes, o que gerou diversos padrões (sintaxes) de criação de módulos, ex.:

• CommonsJS – implementação de módulos do NodeJS;

• AMD (Assynchronous Module Definition) – formato popular proposto por alguns fabricantes de browsers;

• UMD (Universal Module Definition) – formato que combina os dois primeiros e podem rodar no NodeJS e no

browser;

• System – formato que suporta vários formatos;

• ES2015 – formato propostos pelo ECMAScript 2015 e implementado pelo TypeScript.

Módulos

(87)

• Um módulo pode ser considerado como um arquivo que importa ou exporta código fonte; • Cada módulo tem seu próprio contexto, ou seja, seus elementos são visíveis somente dentro

dele, a menos que os exportemos, assim outros módulos podem acessar esses elementos;

• Um module loader é o responsável por carregar os módulos que um importador está

requisitando. O NodeJS (servidor) possui esse loader, mas os browseres (cliente) não, assim temos que usar bibliotecas externar para resolver esse problema. Exemplos:

Módulos

Introdução

Bibliotecas Formatos suportados

RequireJS AMD

(88)

• A exportação de um elemento por um módulo é feita através da palavra reservada export. • A importação de um elemento por um módulo é feita através da palavra reservada import.

Módulos

Sintaxe

import {Carro} from './modelo1';

let uno = new Carro('Uno Hatch', 25000.00);

console.log(`Carro: ${uno.tipo} custa: ${uno.valor}`);

export class Carro{

constructor (public tipo: string, public valor: number){} }

module1.ts

app.ts A importação é feita Informando

entre chaves o que está sendo importado e depois dizemos ao interpretador aonde se encontra o

arquivo do módulo.

O caminho dos módulos podem ser relativos ou absolutos. O primeiro tipo usa três formas: O símbolo “./” identifica um módulo existente na mesma pasta que o arquivo que fez a importação. O símbolo “../” indica que o módulo está

em uma pasta anterior a do arquivo que importou o módulo. O uso do “/” indica que é a pasta raiz da aplicação.

O uso de caminho absoluto são feitos através da propriedade baseUrl no arquivo tsconfig.json.

(89)

import {Carro, printer} from './modelo1';

let uno = new Carro('Uno Hatch', 25000.00);

printer(uno);

Módulos

Exportando vários elementos

module1.ts

app.ts 1) O módulo expôs

dois elementos.

2) O arquivo principal está exportando dois elementos do módulo 1.

export class Carro{

constructor (public tipo: string, public valor: number){} }

export function printer(c: Carro){

console.log(`Carro: ${c.tipo} custa: ${c.valor}`) }

(90)

class Carro{

constructor (public tipo: string, public valor: number){} }

function printer(c: Carro){

console.log(`Carro: ${c.tipo} custa: ${c.valor}`) }

export {Carro, printer}

Módulos

Instrução de exportação module1.ts 1) Podemos centralizar as exportações de elemento somente em uma linha. Instrução de exportação app.ts

import * as m1 from './modelo1';

let uno = new m1.Carro('Uno Hatch', 25000.00);

m1.printer(uno);

2) Podemos importar todos os elementos do

módulo, mas temos que dar um nome de acesso, nesse caso m1.

(91)

class Carro{

constructor (public tipo: string, public valor: number){} }

function printer(c: Carro){

console.log(`Carro: ${c.tipo} custa: ${c.valor}`) }

export {Carro, printer as printerLog}

Módulos

Renomeando os elementos

1) A função foi renomeada no comando de exportação.

import {Carro as Veiculo, printerLog} from './modelo1';

let uno = new Veiculo('Uno Hatch', 25000.00);

printerLog(uno);

2) A classe foi renomeada no comando de importação.

module1.ts

Referências

Documentos relacionados

A espectrofotometria é uma técnica quantitativa e qualitativa, a qual se A espectrofotometria é uma técnica quantitativa e qualitativa, a qual se baseia no fato de que uma

A par disso, analisa-se o papel da tecnologia dentro da escola, o potencial dos recursos tecnológicos como instrumento de trabalho articulado ao desenvolvimento do currículo, e

A elaboração das atividades pautou-se em quatro pontos importantes enumerados por Sasseron (2011) para fundamentar o planejamento de Sequências de Ensino

Como irá trabalhar com JavaServer Faces voltado para um container compatível com a tecnologia Java EE 5, você deverá baixar a versão JSF 1.2, a utilizada nesse tutorial.. Ao baixar

Neste trabalho avaliamos as respostas de duas espécies de aranhas errantes do gênero Ctenus às pistas químicas de presas e predadores e ao tipo de solo (arenoso ou

O objetivo do curso foi oportunizar aos participantes, um contato direto com as plantas nativas do Cerrado para identificação de espécies com potencial

esta espécie foi encontrada em borda de mata ciliar, savana graminosa, savana parque e área de transição mata ciliar e savana.. Observações: Esta espécie ocorre

O valor da reputação dos pseudônimos é igual a 0,8 devido aos fal- sos positivos do mecanismo auxiliar, que acabam por fazer com que a reputação mesmo dos usuários que enviam