Você está na página 1de 96

Introdução ao Typescript

Prof. Bruno Ferreira


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;
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
Introdução ao Typescript
Vantagens

• 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 (?).

Classe com construtores


Classe sem construtores
Introdução ao Typescript
Vantagens

• Mais algumas diferenças:


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.
Classe com propriedades automáticas
Como instalar o Typescript
Node.js e NPM

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.
Como instalar o Typescript
Node.js e NPM

Gerenciador de pacotes
Javascrip. Ou seja,
acessamos um repositório
de bibliotecas para
projetos Javascript
BF1

Como instalar o Typescript


Visual Studio Code

Iremos usar essa


ferramenta dentre as
várias existentes para a
criação do código em
Type Script
Slide 8

BF1 Bruno Ferreira; 03/01/2019


Como instalar o Typescript
Instalando o compilador
1) Utilizamos o npm
• Lanch.json, task.json e tsconfig.json para fazer a instalação
do compilador
Typescript

2) Podemos testar a
instalação requisitando a
versão do programa.
Como instalar o Typescript
Testando o VSCode e o compilador

1) Crie uma pasta


e faça o acesso
via VSCode.

2) Crie um arquivo com


extensão “.ts” e digite o
código.

3) Podemos usar o primeiro


comando para compilar e o
segundo para rodar o
arquivo “.js” criado.

4) Uma outra forma de testar é utilizando o


https://www.typescriptlang.org/play/ compilador online da linguagem
Como instalar o Typescript
Testando o VSCode e o compilador
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.

2) Crie uma pasta


”.vscode” e dentro
{
dessa pasta um
"version": "2.0.0",
arquivos chamado
tasks.json (Terminal >
"tasks": [
3) As propriedades significam respectivamente:
Run Build Task...) {
Versão do compilador, Comando para
"type": "typescript",
compilação, exibir erros no console e, por último,
"tsconfig": "tsconfig.json", qual utilitário pode ser usado para apresentar
"problemMatcher": [ soluções.
"$tsc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
tasks.json

https://www.youtube.com/watch?v=Hs6XWwQUs_A
https://code.visualstudio.com/docs/typescript/typescript-compiling
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á
"compilerOptions": { sendo utilizando e por isso, os arquivos de
"target": "es5", mapeamento para Debug devem ser gerados.
"module": "commonjs",
"sourceMap": true
}
1) Agora temos que }
informar as configurações
tsconfig.json
do projeto em questão,
para isso crie um arquivo
chamado tsconfig.json na
raiz do projeto.
Como instalar o Typescript
Testando o VSCode e o compilador

"version": "0.2.0",
"configurations": [
{
"type": "node", 2) Informe o
"request": "launch", nome do arquivo
"name": "Typescript debug", principal da
"program": "${workspaceFolder}/app.ts", aplicação.
"outFiles": [
"${workspaceFolder}/**/*.js"
]
},
{
"type": "node",
"request": "attach",
1) Agora temos que
informar as configurações
"name": "Attach to process",
do projeto para Debug, "address": "localhost",
para isso crie um arquivo "port": 5858,
chamado laungh.json na "outFiles": [
pasta “.vscode”. "${workspaceFolder}/**/*.js"
]
}
]
}
laungh.json

https://code.visualstudio.com/docs/typescript/typescript-compiling
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.

https://code.visualstudio.com/docs/typescript/typescript-compiling
Como instalar o Typescript
Testando o VSCode e o compilador

• Veja um outro exemplo de código

Crie um arquivo com


extensão “.ts” e digite o
código.
Tipos básicos
Variáveis

• 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:

function teste(i: number){ function teste(i: number){


var teste;
if (i === 10){
2) Esse código não implica
var valor = 20; if (i === 10){
1) Ocorre erro? em erro, a declaração da
} valor = 20; variável com “var” é
else { } transferida para o início
var valor = 30; else { do escopo com o valor
} valor = 30; “undefined”
console.log(valor); }
console.log(valor);
} }
Tipos básicos
Variáveis

• 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


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

function teste(i: number){

if (i === 10){
let valor = 20;
}
else {
let valor = 30;
}
console.log(valor);
Error: runtime – uncaught reference error
}
Tipos básicos
Boolean

• 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.

var isNew: boolean = false;

isNew = true;

Number

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

var age: number = 21;

var pi: number;


pi = 3.141516;
Tipos básicos
String

• Sempre que necessitamos de um texto, recorrermos ao tipo string. Os valores literais


podem ser delimitados por aspas duplas ou simples.

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

nome = "Luis";

Template strings

• Valor literal delimitados por caractere de acento de crase (`) e permitem criar strings
multilinha ou expressões com placeholders utilizando ${xxx} .
let nome = "Luis";
let expressao = ` Olá, ${nome}
tudo bem com você?`;
console.log(expressao);
Tipos básicos
Array

• 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:
var list1: number[] = [1, 2, 3];

let i:any;
for(i in list1) {
Compilador
console.log(list1[i])
exige que a
variável seja }
Acessando
do tipo any um
ou string. var list2: Array<number> = [8,12,33]; elemento
console.log(`Primeiro elemento da lista2 => ${list2[0]}`); específico

var list3: number[]


list3 = [5, 4, 3];
list3.forEach( (p) => console.log(p) );

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


var numeric = ["1", "2", "3"];
Inserindo um
elemento no var alphaNumeric = alpha.concat(numeric);
final do console.log("alphaNumeric : " + alphaNumeric );
array.
alphaNumeric.push("098");
console.log("alphaNumeric : " + alphaNumeric );
Tipos básicos
Array

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

https://www.tutorialspoint.com/typescript/typescript_arrays.htm
Tipos básicos
Array

• Exemplos:

//-----------------------------------
//--------------------------------------- function usaInformacao(value: number) {
var marks:number[] = [58, 68, 74, 88, 64, 90] console.log(value+100);
}
function isPassed(element: number, index: number, array: number[]) { var marks1:number[] = [58, 68, 74, 88, 64, 90]
return (element >= 35) var passA: boolean[];
} marks1.forEach( n => usaInformacao(n));
// ou
var passed = marks.every(isPassed) // marks1.forEach(usaInformacao);
if(passed) //------------------------------------------
console.log("The student has passed.") var numbers = [1, 4, 9];
else var roots = numbers.map(n => Math.sqrt(n));
console.log("The student has failed") console.log("roots is : " + roots );
// ou
//----------------------------------- //var roots = numbers.map(Math.sqrt);
//console.log("roots is : " + roots );

https://www.tutorialspoint.com/typescript/typescript_arrays.htm
Tipos básicos
Array

• 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.

https://www.tutorialspoint.com/typescript/typescript_arrays.htm
Tipos básicos
Array

• Exercício - Solução:

https://www.tutorialspoint.com/typescript/typescript_arrays.htm
Tipos básicos
Exemplos com HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> let input = document.createElement('input');
Introdução ao typescritp input.setAttribute("id", "texto");
</title> input.setAttribute("value", "Entre com o nome");
</head> document.body.appendChild(input);
<body>
<script type="module" src="app.js"></script> var campo: HTMLElement = document.getElementById('texto');

</body>
</html> let button = document.createElement('button');
button.textContent = "Say Hello";
index.htm
button.onclick = function() {
alert(‘Olá’);
if (campo !== null)
alert(campo.getAttribute("value"));
}

document.body.appendChild(button);

https://www.tutorialspoint.com/typescript/typescript_arrays.htm
Tipos básicos
Tupla

• 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:
A primeira e a
segunda
posição do
array terão
respectivamen
te esses tipos.

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


tp[0] = 'Tiao';
As demais posições
// tp[1] = 'Vieira'; <== Erro.
podem assumir
qualquer um dos dois
tipos (number ou tp.push(100);
string). tp.push('Bruno');
tp.forEach((o) => console.log(o));
// tp[3] = true; <== Erro.
Tipos básicos
Enum

• 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.
Como não atribuímos
Podemos calcular o valor,
explicitamente nenhum número
Fazendo a em relação aos outros
aos elementos, o primeiro valor
atribuição membros, nesse caso
terá o numero zero, o segundo
enum SinalSemaforo { enum SinalSemaforo { explícita de enum SinalSemaforo { fazemos uma operação
um, e assim por diante
Verde, Verde = 1, valor. Verde = 1, lógica “ou” bit a bit.
Amarelo, Amarelo = 2, Amarelo = 2,
Vermelho Vermelho= = 6 Vermelho = Verde | Amarelo
} } }

let sinalAtual = SinalSemaforo.Verde; let sinalAtual = SinalSemaforo.Verde; let sinalAtual = SinalSemaforo.Verde;


console.log(sinalAtual); console.log(sinalAtual); console.log(sinalAtual);

Podemos Podemos fazer a


atribuir o direção inversa
sinalAtual = 2;
valor inteiro na busca dos
console.log(sinalAtual); dados.
diretamente.

console.log(SinalSemaforo[sinalAtual]);
Tipos básicos
Any

• 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.
let notSure: any = 4;
notSure = "maybe a string instead";
A variável
console.log(notSure);
assume
diferentes
notSure = false; Poderíamos pensar que Any
tipos ao longo console.log(notSure); é igual a Object, já que esse
do algoritmo. último é o tipo base de
todos os elementos em
let qq: any = 10; Javacript, porém, os
qq = "mudou"; métodos disponíveis para
console.log(qq.lenght); uso são do object e não os
métodos dos tipos básicos
let outro: Object = 10; da linguagem.
outro = "mudou";
console.log(outro.lenght); //<= Error: Property 'lenght' does not exist on type 'Object'.
Tipos básicos
Void

• 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

Função sem
retorno
function warnUser(): void {
console.log("This is my warning message");
}

warnUser();
Tipos básicos
Null, Undefined

• 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;
Podemos declarar let indefinido: undefined;
uma variável do tipo indefinido = undefined;
indefinido, mas não
faz sentido, pois ele só var a;
receberá esse valor.
console.log(typeof a); //resultado> "undefined"
console.log(typeof a === "object"); //resultado> false
Exemplo de
Variáveis não console.log(typeof a === "undefined"); //resultado> true function func(a: number){ uso.
atribuídas são console.log(typeof a == "undefined"); //resultado> true
undefined if (a === undefined)
var b = null; console.log('variável não definida.’);
console.log(typeof b); //resultado> "object" }
Objetos não
console.log(typeof b === "undefined"); //resultado> false
atribuídos são console.log(typeof b === null); //resultado> true var x: number;
null console.log(typeof b == null); //resultado> true func(x);
Tipos básicos
Never

• 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.
Função sem
retorno

function geraErro(): never{ Outro


throw new Error("erro.") exemplo.
} function efetua(opcao: string){
Função com retorno
function Principal(){ indefinido, mas nesse if (opcao === "opc1"){
geraErro(); caso também vai return true;
} retornar never, pois é } else if (opcao === "opc2"){
fruto do fluxo da
return true;
//------ execução.
}
geraErro(); Apenas uma
Exemplo de uso function infiniteLoop(): never { observação,
}
de “never”, while (true) { void e never
indicando que a tem conceitos
}
função não tem diferentes.
}
retorno.
Tipos básicos
Never

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

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.
Tipos básicos
Inferência de tipos

• É 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. Variável do
tipo string.
let outroNome = "Jhony";
outroNome = 42; // <==Erro, tipo incompatível.

Conversão de tipo explícita

• 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:

let someValue1: any = "this is a string"; let someValue3: Object = "this is a string";
let strLength1: number = (<string>someValue1).length; let strLength3: number = (<string>someValue1).length;

let someValue2: any = "this is a string"; let someValue4: Object = "this is a string";
let strLength2: number = (someValue2 as string).length; let strLength4: number = (someValue2 as string).length;
Funções
Funções nomeadas e anônimas

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

Função nomeada
em que espera um
valor string e
retorna também um
string.
function dizOla(nome: string){
return `Olá, ${nome}`; A linguagem aceita
} funções anônimas,
para sua execução
temos que associa-
let imprimeMsg = function (msg: string) : void { la a alguma variável.
console.log(msg);
}

imprimeMsg(”teste!!”);

Uma outra forma de O segundo par de


execução é transformando a parêntese indica o
função em uma expressão local para passar os
com os parênteses “()”. parâmetros da função.
(function() {console.log('anonima 1')})();

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


Funções
Especificação de tipo função

• Funções podem ser usadas para definir novos tipos que, por sua vez, são utilizadas para
tipificar outras variáveis ou parâmetros..
Aqui temos a
Definindo um tipo: Impressora é uma referencia para o
variável que espera uma referencia tipo de retorno.
para uma função que recebe uma
string e não retorna valor. let impressora : (nome: string) => void;

impressora = function(info: string){


Iniciando a variável console.log(info);
com uma função }
válida para seu tipo.
impressora("testando...");

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

Outro exemplo de
função anônima.
var res = function (a: number, b: number)
{
return a * b;
};
console.log(res(12, 2));
Funções
Parâmetros opcionais

• 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 (?).

Marcamos o
parâmetro como
opcional.

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


Atenção: uma função pode definir
if (idade == undefined)
vários parâmetros opcionais, devendo
estes serem sempre colocados depois
console.log(`Olá ${nome}`);
dos parâmetros obrigatórios, se else
existirem. console.log(`Olá ${nome}, você tem ${idade} anos.`);
}

opcionais("Tião",22);
opcionais("Maria"); Chamada com
dois e com um
parâmetro.
Funções
Parâmetros com valores 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.
Definindo valor
padrão para os dois
parâmetros.

Atenção: uma função pode definir function predefinidos (nome: string = "Raul", idade = 20){
vários parâmetros com valores console.log(`Nome: ${nome}, idade ${idade}`);
padrões, devendo estes serem sempre }
colocados depois dos parâmetros sem
valor padrão. predefinidos();
Funções
Parâmetros REST

• 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.

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


parâmetro rest. var i: number;
var sum:number = 0;
for(i = 0;i<nums.length;i++) {
function restParams(nome: string, ...outros:string[]){
sum = sum + nums[i];
return `Nome: ${nome} \n ${outros.join(' ')}`;
“join” cria ums }
} string a partir de console.log("sum of the numbers",sum)
console.log(restParams("Joe", "John", "Gilbert")); um array }
console.log(restParams("Mary"));
O programador addNumbers(1,2,3)
pode optar por addNumbers(10,10,10,10,10);
passar nenhum
parâmetro.
Funções
Funções arrows ou lambdas

• 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).
Exemplo de criação e uso
de funções arrow. Logo
abaixo, vemos a criação do Agora utilizamos o método filter do
mesmo código sem o uso array passando uma função como
var foo1 = (x: number) => 10 + x de funções lambdas. parâmetro. O primeiro exemplo
console.log(foo1(100)) mostra a forma convencional e o
segundo usando funções arrow.
var foo2 = function (x: number) { return 10 + x; }; let numeros = [1,2,3,4,5];
console.log(foo2(100));

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


O uso do parêntese é return valor % 2 === 0}
opcional quando temos );
apenas um parâmetro. console.log(aux1.join(' '));

var display = x => { let aux2 = numeros.filter( (valor, index, arr) => valor % 2 === 0);
console.log("The function got "+x) console.log(aux1.join(' '));
}
display(12);
Tipos básicos
Funções

• 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.

https://www.tutorialspoint.com/typescript/typescript_arrays.htm
Tipos básicos
Funções

• Exercício - Respostas:
let soletrar = function (x: string): string{
x = x.replace("-","");
1) x = x.replace(" ","");
return x.toUpperCase().split("").join("-");
}

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

function isPalindromo(l) {
2) let x = l.split("").reverse().join("");
return (x == l) ? true : false;
}

console.log(isPalindromo('casa'));
console.log(isPalindromo('oborobo')); Primeiro com a função split(), transformei um
console.log(isPalindromo('asa')); string em uma array, tendo uma array eu posso
console.log(isPalindromo('babab')); utilizar a função reverse(), que inverte a ordem dos
console.log(isPalindromo('Frango')); elementos de uma array e por último utilizei a
função join(), que junta os elementos de uma array
em uma string.
Operadores
Aritméticos

• Operadores aritméticos tomam valores numéricos (sejam literais ou variáveis) como seus
operandos e retornam um único valor numérico.
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
Lógico

• Operadores lógicos são utilizados tipicamente com valores booleanos (lógicos); neste
caso, retornam um valor booleano.
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
Associação

• 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 (=).
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.
Operadores
Relacionais

• Um operador relacional compara seus operandos e retorna um valor lógico baseado em


se a comparação é verdadeira.
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.
Operadores === Retorna verdadeiro caso os operandos tenham valores e tipo iguais.
aplicados ao
Javascrip
puro.
!== Retorna verdadeiro caso os operandos tenham valores ou tipos diferente.
Operadores
Relacionais

• Alguns exemplos...
Interface
Introdução

• 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
Sintaxe

• 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.

Para que algum tipo interface Pessoa {


seja compatível
com essa interface nome: String;
ela tem que ter o imprime: () => void;
mesmo atributo e }
método.

Qualquer variável
que tem a estrutura
da interface poderá
function imprime(p: Pessoa){ ser passada como
if (!p.nome){ parâmetro nessa
p.nome = 'Sem nome'; função.
}
p.imprime();
}
Interface Uma alternativa ao uso
de interface é declarar o
parâmetro como um
Sintaxe objeto, nesse caso, todo
objeto que tenha a
propriedade label do tipo

• Exemplo string pode ser passado


como parâmetro.

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


console.log(labelledObj.label);
}

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


printLabel1(myObj1);

interface LabelledValue { Agora o mesmo exemplo é


label: string; implementado com o uso
} de interface, apesar de
termos um código com
function printLabel2(labelledObj: LabelledValue) { mais linhas, a legibilidade
console.log(labelledObj.label); com o uso de interface é
} indiscutível.

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


printLabel2(myObj2);
Interface
Sintaxe

• Evitando erros

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

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


{
// ...
return null;
}

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

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.
Interface
Membros opcionais

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


caractere “?”.

Qualquer objeto
que apresente uma interface OutraPessoa {
propriedade
designada por nome: String;
“nome” é imprime?: () => void;
considerada }
compatível.

function imprimir(p: OutraPessoa){

if (!p.nome){
Membros opcionais p.nome = 'Sem nome';
obriga-nos a ter
}
algum cuidado na
if (p.imprime){
interação com
objetos
p.imprime();
compatíveis. } else {
console.log (`Sem membro imprime: ${p.nome}`);
}
}
Interface
Membros somente leitura

• 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.

Podemos atribuir o
valor ao membro
“nome” somente
uma vez, a linha de
Informando que interface AlunoInterno{ baixo resultaria em
o campo é readonly nome: string; erro.
somente }
leitura.
let aluno: AlunoInterno = {nome: 'Jimy'};
aluno.nome = 'Jhon’; // Erro de compilação
Interface
Herança de interfaces

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

Uma interface
pode herdar
interface Pessoa { membros de várias
outras interfaces
nome: String; usando a virgula (,)
imprime: () => void; para declará-la.
Uma variável que }
pertence ao tipo Aluno
terá as propriedades interface Aluno extends Pessoa{
nome e turma, além do turma: string;
método opcional }
“imprime”
Interface
Compatibilidade de interfaces com objetos literais

• Primeiro vamos entender o que são objetos literais. Literais são maneiras menores para
var carro = { definir objetos. Basta inserir entre
marca: "Ford", chaves as propriedades e métodos de
modelo: "Ka", um objeto. Nesse caso o objeto já é
getDetalhes: function () { instanciado e referenciado pelo nome
da variável que ele foi atribuído.
return this.marca + ' - ' + this.modelo;
}
}

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


interface Atendente{
nome: string;
}

function imprimeNome(user: Atendente){


Como mecanismo de console.log(user.nome);
segurança, a atribuição de }
objetos literais diretamente a
parâmetros do tipo de uma imprimeNome({nome: 'Luiz', endereco: 'Rua 23’}); //  Erro Para burlar esse
interface, só é permitida se var u: Atendente = {nome: 'Luiz', endereco: 'Rua 23’}; //  Erro mecanismo de
esse objeto definir apenas segurança, pode-se
propriedades compatíveis com var at1 = {nome: 'Luiz', endereco: 'Rua 23'}; usar uma variável
as da interface. Nesse exemplo auxiliar ou fazer uma
imprimeNome(at1);
a propriedade “endereço” não conversão explícita.
existe na interface.
var u: Atendente = {nome: 'Luiz', endereco: 'Rua 23'} as Atendente;
Interface
Funções

• 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.

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;

interface Existe{
(nome:string): boolean;
}

2) Tipificamos uma let nomes = ['Rui','Jhon','Jimmy','Robert','Fancisca’];


variável que agora espera
uma função que é let pesquisa: Existe = (n) => nomes.indexOf(n) >= 0;
responsável por indicar 3) Ao definir a função,
se um nome está console.log(pesquisa('Robert')); podemos usar outros nomes
presente em um array. console.log(pesquisa('Maria')); para os parâmetros e não
precisamos definir o tipo, pois
o compilador usa o tipo
declarado na interface.
Classes
Introduçã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.
1) Nome da classe

class Pessoa{
nome: String;
2) Definimos um construtor.
constructor(nome: string){ 3) A classe tem uma
this.nome = nome; propriedade e um método.
}

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


}
4) Instanciando um objeto.
let n1 = new Pessoa('Tião');
Classes
Visibilidade

• 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.

class Pessoa2{
class Pessoa{
2) Esse membro só private nome: String;
public nome: String;
pode ser acessado
dentro da classe. constructor(nome: string){
public constructor(nome: string){
this.nome = nome; this.nome = nome;
} }

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


} }

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


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

1) Podemos
explicitar a
visibilidade, mesmo
que o padrão é let m3: Pessoa = new Pessoa2('Robert'); 3) Dois objetos são compatíveis quando
public. os tipos, nomes e visibilidade das
propriedades são os mesmo. Nesse caso, o
compilador acusaria um erro.
Classes
Parâmetros como propriedades

• 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.

class Mamiferos{ 1) A classe tem a


propriedade “nome”
que é privada.
constructor(private nome: string){
}

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

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


gato.imprimirNome;
Classes
Getters e Setters

• As propriedades podem ser vistas como campos onde o acesso de leitura ou escrita é
feito através do uso de métodos especiais.
class Aves{
private _nome: string;

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


1) Esses métodos
acessam a get nome(){
propriedade _nome, return this._nome;
eles são uteis para }
proteger as variáveis
de atribuições
set nome(nome: string){
incorretas.
if (!nome)
console.error('Erro. nome obrigatório’);
else
this._nome = nome;
}

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


1) Deve-se acessar as }
propriedades pelos
nomes dos métodos. let ave = new Aves('Galinha');
Mas as métodos são ave.imprimirNome();
acessados como ave.nome = 'Faizão';
propriedades. ave.imprimirNome();
Classes
Membros opcionais

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

1) O campo idade e o class MembrosOpcionais{


método são opcionais.
Como o método é nome: string;
opcional não precisa de idade?: number;
definir o seu corpo. imprimeIdade?(): string;
}

var mOp = new MembrosOpcionais();

if (mOp.imprimeIdade)
2) Os membros opcionais console.log(mOp.imprimeIdade)
podem retornar o tipo
undefined, sendo assim, temos
que fazer o teste antes do uso
dos métodos opcionais.
Classes
Membros estáticos

• 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.

1) Declaramos class Grid{


um membro static Origem = {x: 0, y:0};
estático.
calculaDistancia(ponto: {x: number, y:number}){
let xD = (ponto.x - Grid.Origem.x);
let yD = (ponto.y - Grid.Origem.y); 2) Utilizamos o membro
return Math.sqrt(xD * xD + yD * yD); estático para calculo da
} distância, repare que o uso é
feito através do nome da classe.
constructor (public escala: number){};
}

3) Mais um exemplo de let distancia = new Grid(1).calculaDistancia({x:11, y:11});


uso de um membro console.log(distancia);
estático. console.log(Grid.Origem.x);
Classes
Herança

• 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. 1) Herdamos os
membros da
class Aluno extends Pessoa{ classe Pessoa.
private _idade: number;

2) A classe é obrigado a invocar constructor(nome: string, idade: number){


o construtor da classe pai super(nome);
através da palavra super. this._idade = i;
};

get idade(){
return this._idade;
}
4) Seguindo os conceitos da OO
set idade(valor: number){ clássica, pode-se declarar
this.idade = valor; membros com encapsulamento
} protected. Esse nível de acesso
} restringe a utilização dos
3) Podemos acessar os membros somente à classe ou
métodos públicos let aluno1 = new Aluno('Johny', 23); às classes filhas.
herdados pela classe. aluno1.nome = 'Johny Lemos';
Classes
Classes abstratas

• 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.

1) Não podemos 2) Método que


instanciar deve ser
objetos da classe abstract class Base{ implementando
abstrata. pelas classes
nome: string;
abstract dizOla(); filhas.
}

3) Implementação do class Derivada extends Base{


método abstrato. dizOla(){
console.log('Ola!!!’);
}
}

let derivada = new Derivada();


derivada.dizOla();
Classes
Classes usadas como interface

• 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.
class Ponto{
x: number; 1) A interface herda
y: number; apenas a forma dos
membros, ou seja, se a
}
classe tiver algum método,
a interface herda somente
interface Ponto3d extends Ponto{ a assinatura do método,
z: number; não a sua implementação.
}

function imprimePonto(p: Ponto3d){


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

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


três membros da pTeste.x = 10;
interface. Sendo pTeste.y = 20;
que x e y foram pTeste.z = 30;
herdados.
imprimePonto(pTeste);
Outros tipo
Unions

• Typescript permite que um parâmetro ou uma variável assuma mais de um tipo. Esse
conceito é chamado de união de tipos (“|”).
1) Usamos o conceito de
união para definir que o
parâmetro poderá ser do
tipo string ou number.

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);
2) Usamos a console.log(r);
função com os 3) O tipo “any” poderia ter
r = padLeft('Texto..','Inicio');
dois tipos de sido usado, contudo, o
console.log(r);
parâmetros. usuário tem a possibilidade
de usar um tipo boolean, o
que não é o desejado.
Outros tipo
Unions

class Cliente { interface Bird {


endereco: string; raca: string;
constructor(public nome: string){} fly();
} layEggs();
}
class Fornecedor {
telefone: string; interface Fish {
constructor(public nome: string){} raca: string;
} swim();
layEggs();
1) Quando recorremos a }
let x1: Cliente|Fornecedor;
x1 = new Cliente('Jorge'); uma união para definir o
tipo de um objeto, o function getSmallPet(): Fish | Bird {
x1.endereco = 'Rua do centro';
compilador só permite o let f: Fish;
console.log(x1.endereco);
uso de membros comum return f;
ao tipo instanciado. }
x1 = new Fornecedor('Farmácia');
x1.telefone = '2222-2222'; 2) Quando recorremos
console.log(x1.telefone); let pet = getSmallPet(); a valores que tem o
pet.layEggs(); // Correto tipo união, somente os
pet.swim(); // Erro membros em comum
dos tipos podem ser
utilizados.
Outros tipo
Guardas

• 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. •Para strings, typeof retorna“string.”
•Para numbers, typeof retorna“number.”
•Para booleans, typeof retorna“boolean.”
•Para undefined, typeof retorna“undefined.”
• 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:
let aa: number = 9;
console.log(typeof aa); // "mumber"
console.log(typeof {}); // "object" 1) Não descobrimos qual a
console.log(typeof []); // "object" classe do objeto, somos
console.log(typeof new Date()); // "object" informados apenas que é
console.log(typeof new RegExp('')); // "object" um objeto.
console.log(typeof null); // "object"
Outros tipo
Guardas

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


console.log({} instanceof Object); // "object"
console.log([] instanceof Array); // "object"
console.log( new Date() instanceof Date); // "object"
console.log(new RegExp('') instanceof RegExp); // "object"

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


objeto: 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`
}
}
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. 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
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á
compostos pela união de todos os membros desses tipos.

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
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 {
1) Usamos a palavra
if (typeof n === "string") {
reservada type para criar
return n;
os apelidos. Podemos criar
}
apelidos utilizando outros
apelidos e dar apelidos else
para tipos funções. 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}` );
}
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");
//button.animate(0, 0, "uneasy"); <== Erro
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
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

let list = [4, 5, 6]; let iterar = {nome: 'Bruno’,


sobrenome: 'Ferreira'};
for (let i in list) {
2) O primeiro laço
console.log(i); // "0", "1", "2", 1) O primeiro laço retorna o nome das for (let i in iterar) {
} retorna os índices, o propriedades, o console.log(i);
segundo os valores segundo mostra um }
for (let i of list) { desses índices. erro de compilação, for (let i of iterar) {
console.log(i); // "4", "5", "6" pois o objeto não é console.log(i);
} iterable. }
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.

class Flies {
fly() {
console.log('voando...'); 1) Começamos com
} duas classes simples
} que representam
superpoderes de
class Climbs { heróis.
climb() {
console.log(‘subindo na parede');
}
}
Outros tipo 2) Criamos uma terceira classe que
herda os poderes das duas
primeiras classes (herança
Mixim ou herança múltiplas múltipla), para qual usamos a
palavra chave implements.

class BeetleGuy implements Climbs, Flies {


climb: () => void;
fly: () => void;
3) Redeclaramos todos os
métodos como propriedades, sting(){
nesse caso, não existiam this.fly();
propriedades a serem herdadas. this.climb(); 4) Criamos o seguinte método
console.log('ferroa!!'); 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
function applyMixins(derivedCtor: any, baseCtors: any[]) { em um módulo para ser aplicado
baseCtors.forEach(baseCtor => { quando necessário.
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
if (name !== 'constructor') {
derivedCtor.prototype[name] = baseCtor.prototype[name];
}
5) Registramos a classe com });
herança múltipla utilizando o });
método criado e, por fim, }
utilizamos a nova classe
instanciando um objeto. applyMixins (BeetleGuy, [Climbs, Flies]);

let superBesouro = new BeetleGuy();


superBesouro.sting();
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.

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


return parametro1 == parametro2;
} 2) Definimos o tipo
da função quando
3) Se omitirmos o ela é invocada.
placeholder, o console.log(compara<number>(10,20));
compilador tentará console.log(compara<string>('bh','sp’));
inferir o tipo.
console.log(compara(true,true));
Outros tipo 3) Se omitirmos o
placeholder, o
compilador tentará
Generics inferir o tipo.

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


function identity<T>(arg: T): T {
1) Usamos o nome “T” para a definição da
return arg;
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.
let myIdentity: <U>(arg: U) => U = identity;
console.log(myIdentity(3000));

• Pode-se utilizar generics em funções de uma interface, isso pode ser feito de duas formas:
2) Declaramos o
2) Declaramos o tipo genérico na
interface Molde { tipo genérico na interface Molde<T> { definição da
<T>(arg: T): T; função da interface. interface.
(arg: T): T;
} }

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


return arg; return arg;
} }

let myIdentity: Molde = identidade; let myIdentity: Molde<number> = identidade;


console.log(myIdentity<number>(1000)); console.log(myIdentity(1000));
Outros tipo
Generics

• Pode-se utilizar generics em classes, isso pode ser feito da seguinte forma:
class AdicionaGenerico<T> {
1) Classe com o valorInicial: T;
tipo genérico add: (x: T, y: T) => T;
definido na }
declaração da
classe. let myGenericNumber = new AdicionaGenerico<number>();
myGenericNumber.valorInicial = 0; 2) Instanciamos
dois objetos com
myGenericNumber.add = function(x, y) { return x + y; };
tipos diferentes.
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"));

• Outro exemplo:
class Generica<U>{
3) Propriedade
constructor(public t: U){}
definida com
}
generics no
let g = new Generica<boolean>(true);
construtor
console.log(g.t);
Outros tipo
Generics Constraints

• 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:
function registrar<T>(arg: T): T {
1) Essa linha apresenta um
erro, o compilador não console.log(arg.length);
reconhece o método lenght return arg;
}

• 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:

interface Comprimento {
length: number;
}

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


console.log(arg.length);
return arg;
}
Outros tipo interface PropriedadeNome{
nome:string;
Generics Constraints }

class PessoaFisica{
• Outro exemplo: constructor(public nome: string){}
}

class PessoaJuridica{
constructor(public nome: string){}
1) O tipo Y tem a }
propriedade nome.

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


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

• 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];
}
2) O tipo k têm os mesmos
membros que o elemento T.
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
Tipo Promises

• 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
let pr = new Promise ( (resolve, reject) => {

// resolva ou rejeite
});

• 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 1) Nome padrão das
Tipo Promises funções para aceitar e
rejeitar a promessa.

• Exemplo 1: let pr = new Promise ( (resolve, reject) => {

2) Quando executarmos a resolve(10); 2) O método then é acionado


promessa, ela dirá que o }); com a promessa resolvida. A
processamento foi resolvido e variável “valor” recupera o
o valor final é 10. retorno da promessa.
pr.then(valor => console.log(value));

• 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.

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

resolve(100);
});
4) Caso o método reject tivesse
pr2.then( (valor) => {console.log(valor); return 200;})
sido acionado dentro da
promise, o catch seria .then( (v) => console.log(v))
executado. .catch( (err) => console.log('erro!'));
Outros tipo
Tipo Promises 1) Geralmente usamos
Promise como retorno
de funções.
• Exemplo 2:
function abrirArquivo() : Promise<String>{

return new Promise( (resolve,reject) => { function fecharArquivo() : Promise<String>{

//abrindo o arquivo... return new Promise( (resolve,reject) => {


let correto = true;
if (correto) //abrindo o arquivo...
resolve("Aberto..") let correto = true;
reject("erro ao abrir o arquivo.") if (correto)
}); resolve("Fechando..") 2) Uma das grandes vantagens
} reject("erro ao fechar o arquivo.") de Promise é que podemos
encadear ações em ambientes
});
assíncronos. Contudo,
}
function lerArquivo() : Promise<String>{ simulamos uma ação de três
passos que é o de abrir, ler e
fechar um arquivo.
return new Promise( (resolve,reject) => { abrirArquivo()
.then( () => lerArquivo()
//abrindo o arquivo... .then( () => fecharArquivo()
let correto = false; .then( () => console.log('tudo certo!'))
if (correto) .catch( (errFechar) => console.log(errFechar))
resolve("Lendo..") .catch( (errLer) => console.log(errLer) ) ) )
reject("erro ao ler o arquivo.") .catch( (errAbrrir) => console.log(errAbrrir));
});
}
Outros tipo
Promises têm também alguns métodos estáticos úteis

• 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.
Módulos
Introdução

• 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
Introdução

• 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:

Bibliotecas Formatos suportados


RequireJS AMD
SystemJS CommunsJS, AMD ou ECMASCript2015
Módulos
Sintaxe

• 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.

export class Carro{


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

O caminho dos módulos podem ser relativos ou absolutos.


O primeiro tipo usa três formas: O símbolo “./” identifica
A importação é feita Informando um módulo existente na mesma pasta que o arquivo que
entre chaves o que está sendo fez a importação. O símbolo “../” indica que o módulo está
importado e depois dizemos ao em uma pasta anterior a do arquivo que importou o
interpretador aonde se encontra o módulo. O uso do “/” indica que é a pasta raiz da aplicação.
arquivo do módulo. O uso de caminho absoluto são feitos através da
propriedade baseUrl no arquivo tsconfig.json.
import {Carro} from './modelo1';

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


console.log(`Carro: ${uno.tipo} custa: ${uno.valor}`);
app.ts
Módulos
Exportando vários elementos

export class Carro{

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


1) O módulo expôs }
dois elementos.
export function printer(c: Carro){

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


}
module1.ts

2) O arquivo principal está exportando


dois elementos do módulo 1.

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

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


printer(uno);
app.ts
Módulos
Instrução de exportação
class Carro{

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


}

function printer(c: Carro){

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


1) Podemos centralizar }
as exportações de
elemento somente em
export {Carro, printer}
uma linha.
module1.ts

Instrução de exportação

import * as m1 from './modelo1';

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


2) Podemos importar m1.printer(uno);
todos os elementos do
módulo, mas temos app.ts
que dar um nome de
acesso, nesse caso m1.
Módulos
Renomeando os elementos

class Carro{

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


}

function printer(c: Carro){

console.log(`Carro: ${c.tipo} custa: ${c.valor}`) 1) A função foi renomeada


} no comando de exportação.

export {Carro, printer as printerLog}


module1.ts

2) A classe foi renomeada


no comando de importação.

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

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


printerLog(uno);
app.ts
Módulos
Exportações predefinidas

Quando o módulo possui apenas um elemento, pode-se fazer uma exportação predefinida.
Assim o nome do elemento é informado somente na hora da importação.

export default class {


1) Usamos a palavra
reservada default e não constructor (public modelo: string, public valor: number){}
damos nome a classe. }
module2.ts

2) Informamos o nome da
classe no momento da
importação.

import Cc from './modulo2';

let truck1 = new Cc('Carreta Volvo', 250000.00);


console.log(truck1.modelo);
app.ts
Módulos
Reexportando módulos

Um módulo pode utilizar outros módulos para criar seus elementos. É comum também que esse
módulo exponha os elementos importados, isso deixa a implementação transparente e da a
impressão que existe somente um arquivo.
3) O script principal importou
1) Esse módulo importou o somente o módulo 2, e usa
tipo Veículo do módulo 1. sem saber uma classe que foi
declarada em módulo 1.

import {Veiculo} from './modelo1';


class Veiculo{ import {Veiculo, Moto} from './modulo2';
class Moto extends Veiculo{
constructor(public qtdeRodas: number){} let bike = new Veiculo(2);
constructor(public modelo: string){
} console.log(bike.qtdeRodas);
super(2)
}
export {Veiculo}; let moto = new Moto('Honda XR250');
}
module1.ts console.log(moto.modelo);
export {Veiculo, Moto}; app.ts
module2.ts

2) O Módulo 2 exportou os
elementos dele e do módulo 1.
Módulos 1) Tipo Regex não
recebe uma string

Namespaces namespace Validacao{


let emailRegex: RegExp = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
let urlRegex: RegExp = /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-
Namespace é um tipo de ]*)*\/?$/;
módulo interno ao arquivo. export class EmailValidator{
static isValide(str:string):boolean{
return emailRegex.test(str);
}
}
2) Duas classes expostas
utilizando export. export class UrlValidator{
static isValide(str:string):boolean{
return urlRegex.test(str);
}
}
3) Dentro do mesmo arquivo,
mas agora somos obrigados a }
importar as classes, nesse
momento podemos dar nomes import EmailValidator = Validacao.EmailValidator;
diferentes às classes. import URLValidator = Validacao.UrlValidator;

4) Finalmente,
let emailExamples = ["teste","teste@teste","teste@teste.com"]; podemos utilizar as
let urlExamples = ["ifmg", "ifmg.edu.br","www.formiga.ifmg.edu.br"]; classes

emailExamples.forEach(email => console.log(`${email}


${EmailValidator.isValide(email)}`));
urlExamples.forEach(url => console.log(`${url} ${URLValidator.isValide(url)}`));
https://code.tutsplus.com/tutorials/8-regular-expressions-you-should-know--net-6149 app.ts
ANEXO I
Sites com material extra
Fala sobre o operador keyof
http://www.diullei.com/2017/03/31/keyof/

Menciona sobre index type


https://medium.com/@oieduardorabelo/typescript-o-guia-definitivo-1a63b04259cc

Exemplo de dicionários:
https://gist.github.com/OliverJAsh/2a538639e35db183b0cc16ca8ab520a7

Texto sobre iterators e generators


https://braziljs.org/blog/generators-yield-e-iterators/
Referencias
https://www.youtube.com/watch?v=a5De3EeLA9Q&list=PL62G
310vn6nGg5OzjxE8FbYDzCs_UqrUs&index=2

https://www.typescriptlang.org/docs/home.html

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

https://www.devmedia.com.br/curso/curso-de-typescript/422

Typescript Fundamentals
https://www.youtube.com/watch?v=bAPJ2
W6Fr4Q&list=PL6tu16kXT9Pp6XV3L3lrWide
BW6Mcwaa5 Typescript: o Javascript Moderno Para
Criação de Aplicações - Luís Abreu

Você também pode gostar