Você está na página 1de 23

Introdução ao TypeScript

Veremos o TypeScript, um superset da linguagem JavaScript criado pela Microsoft para permitir a escrita de

scripts com a utilização de tipagem estática, orientação a objetos, e facilitando a escrita de código com uma

sintaxe de fácil compreensão

A linguagem TypeScript surge como um superset do JavaScript, adicionando a este


funcionalidades que nativamente não estão disponíveis ou requerem grande esforço
para utilização, como tipagem de dados e Orientação a Objetos. Conhecer essa nova
opção de desenvolvimento é útil para aqueles que utilizam JavaScript intensamente em seus
projetos e desejam construir códigos com melhor arquitetura, aplicando padrões de projeto
e práticas comumente encontradas em outras linguagens orientadas a objetos.

Guia do artigo:

 O que é o TypeScript?
 ECMAScript 6
 Orientação a Objetos
 Encapsulamento
 Herança
 Abstração
 Polimorfismo
 Trabalhando com o TypeScript
 Tipos de dado: Any
 Let, Var e Const
 Generics
 Modules
 Interfaces
 TypeScript Playground
 Cross-browser
 TypeScript no Visual Studio
 Utilizando tipagem estática
 TypeScript com AngularJS
 Criando a Interface

Ao longo da nossa trajetória como desenvolvedores de sistemas web, nos deparamos com a
necessidade de utilizarmos a linguagem de programação JavaScript em várias das nossas
aplicações. Considerada uma das linguagens mais populares do mercado, ela ainda não
possui, mesmo com tanto tempo no mercado, alguns recursos e características normalmente
necessárias no desenvolvimento de software de grande escala.

Diferentemente do que ocorria alguns anos atrás, onde JavaScript era utilizada apenas no
lado cliente das aplicações, atuando na validação de formulários e composição de elementos
da interface, atualmente temos iniciativas que levam essa linguagem a representar a parte
principal de aplicações mobile (em frameworks de desenvolvimento híbrido como Apache
Cordova) e web (no lado servidor com Node.js). Nestes cenários, os projetos não se
resumem mais a pequenos arquivos com algumas linhas de código, muitas vezes apenas
utilizando outros frameworks front-end. Agora, passa a ser necessária a possibilidade de
construir arquiteturas mais sólidas, onde se possa organizar adequadamente o código e
aplicar as melhores práticas e técnicas de programação, como a Orientação a Objetos e,
dentro desta, o uso de interfaces.

O que é o TypeScript?

Criada pela Microsoft, TypeScript está provando ser uma escolha comum entre os
desenvolvedores ASP.NET. Não se trata, na verdade, de uma linguagem completamente
nova, mas sim um superset (ou superconjunto) do JavaScript.

Com TypeScript dispomos de recursos que melhor suportam o uso da Programação


Orientada a Objetos, que tem como base quatro princípios fundamentais: encapsulamento,
herança, abstração e polimorfismo, os quais veremos de forma mais detalhada a seguir. A
POO sempre foi um problema ao ser aplicada em JavaScript, devido a sua sintaxe não
permitir escrever classes, por exemplo, de forma tão clara, além da fraca tipagem de
dados. O TypeScript oferece então uma forma de corrigir ou contornar esses
problemas, adicionando funcionalidades que quando compiladas resultarão em código
JavaScript novamente. Porém, agora o desenvolvedor lidará diretamente com uma sintaxe
simplificada, mais clara e amplamente suportada por editores de código modernos.

O TypeScript, que no momento da publicação deste artigo encontrava-se em sua versão 1.8,
teve como seu principal desenvolvedor o mesmo criador da linguagem C#, Anders Hejlsberg,
e sua equipe na Microsoft. Visando aproveitar o máximo da linguagem e contar com a
adesão e colaboração da comunidade técnica, o projeto é open source e baseia-se nos
padrões ES6 (ECMAScript), que podem ser compilados para JavaScript.

Por ser um superconjunto do JavaScript, qualquer código dessa linguagem pode ser
colocado em um arquivo TypeScript, que possui a sua extensão .ts, e utilizado diretamente.
Este é um ponto bastante positivo, pois podemos utilizar códigos JavaScript já existentes,
sem a necessidade de realizarmos grandes conversões. Uma vez que tenhamos um arquivo
TypeScript salvo, podemos compilá-lo para JavaScript utilizando a ferramenta de compilação
tsc.exe, ou mesmo utilizando task runners (BOX 1) como o Grunt ou mesmo o Gulp.

BOX 1: Task Runner

Muitas vezes, durante o desenvolvimento de softwares, é preciso executar


tarefas que se repetem com certa frequência, como concatenação,
minificação de arquivos, e testes. Os Task Runners são ferramentas
utilizadas para automatizar esse tipo de tarefa. O Grunt e o Gulp são
exemplos desse tipo de ferramenta para JavaScript, havendo vários no
mercado para outras linguagens que, baseados em arquivos de
configuração onde as tarefas são definidas, as executam em determinado
momento durante o desenvolvimento, como no build da aplicação.
ECMAScript 6

ECMAScript é uma especificação de linguagens de script com marca registrada padronizada


pela Ecma International nos padrões ECMA-262 e ISO/IEC 16262. Algumas das
implementações que conhecemos desta padronização estão no JavaScript, JScript e
também no ActionScript, os quais são bastante utilizados em aplicações web no client-side.
Com a evolução da Web e o alto uso de scripts, novas metas foram definidas pelo
ECMAScript 2015 (também chamado ES6), as quais incluem o fornecimento de um melhor
suporte para grandes aplicações, criação de bibliotecas, além do uso de ECMAScript em
outras linguagens. Algumas de suas principais melhorias incluem módulos, declarações de
classe, promises para programação assíncrona, dentre outras. A biblioteca do ECMAScript
foi expandida para suportar abstrações de dados adicionais, incluindo mapas, conjuntos e
matrizes de valores numéricos, bem como suporte adicional para caracteres Unicode em
strings e expressões regulares.

Baseado nas especificações do ES 6, o TypeScript é capaz de oferecer recursos como


interfaces e generics, características já presentes em outras linguagens de programação
orientadas a objetos, como C# e Java.

Princípios básicos da Orientação a Objetos

Para que possamos compreender melhor as diferenças de escrita de código entre TypeScript
e JavaScript “puro”, é importante que tenhamos conhecimento dos princípios básicos do
paradigma da Orientação a Objetos. A seguir, veremos o conceito e exemplos de como
aplicar cada princípio em TypeScript.

Encapsulamento

O conceito de encapsulamento define uma forma de estruturar o código para que um


determinado bloco tenha pontos de acesso específicos para o ambiente externo, o que
garante a visibilidade e acessibilidade controladas dos elementos internos da classe.

Por meio do encapsulamento pode-se definir quais atributos da classe serão visíveis para
utilizadores externos, e a forma como serão expostos ao uso por meio da interface pública do
componente. No .NET Framework, por exemplo, quem trabalha com C# está acostumado a
declarar atributos privados nas classes e suas respectivas propriedades públicas que os
encapsulam. O exemplo a seguir mostra o equivalente a essa prática em TypeScript:

1 private _saldo: number;


2 get Saldo(): number { return this._saldo; }

Observe que já neste trecho podemos ver a tipagem de dados e modificadores de acesso.
Herança

Segundo o princípio da herança, uma classe (filha) pode herdar de outra (pai) características
e comportamentos já definidas nessa segunda, sem necessidade de redefinição. A sintaxe
em TypeScript para implementar esse conceito é semelhante à da linguagem Java, onde se
usa a palavra reservada extends após o nome da classe filha, seguida do nome da classe
pai, como podemos ver na Listagem 1.

1 module Banco {
2   class Conta { ...código aqui.. }
3   class ContaCorrente extends Conta { ...código aqui.. }
4   class Poupanca extends Conta { ...código aqui.. }
5 }

Listagem 1. Utilização de herança no TypeScript

Diferente do JavaScript tradicional, que normalmente é extenso e as classes definidas por


meio da palavra reservada function, temos um código muito mais simples e compreensível
quando utilizamos o TypeScript. Aqui podemos perceber de forma clara a utilização da
herança. Para nós é mais fácil escrever códigos com o TypeScript e deixar que ele se
encarregue de gerar o código JavaScript que nos custaria mais tempo para escrita e
compreensão posterior.

Abstração

No contexto da Orientação a Objetos, a abstração é a capacidade de destacar as


características dos elementos do mundo real que serão úteis para o sistema. Essas
características são reunidas na forma de classes, que representam as “coisas” reais a serem
utilizadas no domínio do problema.

Dentro do conceito de classes, temos ainda as classes abstratas, que até a versão 1.8 do
TypeScript, utilizada neste artigo, ainda eram suportadas diretamente, no entanto, podemos
utilizar interfaces para implementar esse princípio, como podemos ver na Listagem 2.

export module BancoDevmedia


1
{
2
   export interface Taxa { MudarTaxa(valor:
3
number); }
4
   export class ContaCorrente implements Taxa {
5
       MudarTaxa(valor: number) { }
6
   }
7 }

Listagem 2. Abstração com TypeScript por meio de interfaces


Polimorfismo

Polimorfismo é um conceito a partir do qual objetos podem assumir formas diferentes em


determinadas situações, mas mantendo uma relação com sua definição inicial de nível mais
alto. Aliado ao conceito de herança, o polimorfismo indica que um objeto do tipo de uma
classe pai pode assumir a forma de qualquer uma de suas classes filhas, mas não o inverso.

O Typescript permite a utilização de polimorfismo através de métodos, como mostra


a Listagem 3, onde podemos realizar operações bancárias em classes derivadas de uma
classe base. O método TrocarTaxa foi originalmente definido na classe Conta, no entanto, foi
sobrescrito na classe filha ContaCorrente para apresentar um comportamento específico
quando acionado.

1 class ContaCorrente extends Conta


{
2
   TrocaTaxa(valor: number)
3
   {
4
       if (this.Saldo > 50000) { valor =
5
0; }
6
       else { valor += 10.00; } 
7
       this.Saldo =+ valor;
8    }
9}

Listagem 3. Utilizando o Polimorfismo

Após essa pequena abordagem sobre a Orientação a Objetos, passaremos a ver as


características básicas do TypeScript.Trabalhando com o TypeScript

Assim como nas demais linguagens de programação, os tipos básicos de dados encontram-
se também no TypeScript, como o Boolean, String, Array, number, dentre outros.

O tipo mais básico encontrado aqui é o Boolean, cujo valor pode ser true ou false. Além dele,
como no JavaScript, todos os valores numéricos no TypeScript são de ponto flutuante, os
quais recebem o tipo number. Além dos tipos hexadecimal e decimal, o TypeScript também
suporta binários e octais, que foram introduzidos no ES6. Os arrays no TypeScript podem ser
inseridos de duas maneiras diferentes: com a utilização dos colchetes ou por meio de um
array genérico.

Na Listagem 4 podemos ver vários exemplos de declaração e atribuição de valores a


variáveis de diversos tipos.

1 01 let estaAtivo: boolean = false;


2 02 let qtdSorvete: number = 10;
3 03 let nomeCompleto: string = “Edson Dionisio”;
4 04 let numerosPares: number[] = [2, 4, 6, 8]; //conjunto de inteiros utilizando colchetes.
5 05 let numerosImpar: Array<number> = [1, 3, 5, 7, 9];
6 //conjunto de inteiros utilizando array genérico.

Listagem 4. Definição dos tipos básicos no TypeScript

Além dos tipos básicos apresentados, temos ainda o tipo Enum, que assim como no C#, é
utilizado para atribuirmos nomes amigáveis para conjuntos de valores numéricos. Por
padrão, os enums são numerados a partir do 0, podendo ser modificada essa configuração
de forma manual, se necessário. Também podemos obter o nome de um determinado valor a
partir da sua numeração, como podemos ver na Listagem 5.

1 // Definição do Enum
2 enum Color {Red, Green, Blue};
3 let c: Color = Color.Green;
4 // Iniciando o Enum com um valor diferente de 0
5 enum Color {Red = 1, Green, Blue};
6 let c: Color = Color.Green;
7 // Pegando o valor a partir da numeração
8 let colorName: string = Color[2];

Listagem 5. Utilização de Enums no TypeScript

Tipos de dado “Any”

Em determinadas situações pode haver dúvida sobre qual tipo de dados utilizar para
representar um certo valor. Essa questão é comum quando trabalhamos com aplicações de
terceiros, onde devemos obter um determinado resultado, mas não sabemos qual foi o
padrão utilizado para a disposição das informações. Para isso, temos à nossa disposição o
tipo de dados Any, que permite a passagem dos dados sem que haja a verificação do tipo.
Esse tipo é bastante útil e poderoso quando precisamos trabalhar com códigos JavaScript já
existentes, permitindo que possamos otimizar o código da melhor forma, gradualmente, sem
a necessidade de verificar o tipo de dados no momento da compilação. O trecho de código a
seguir exemplifica o uso do Any:

1 let tipoDado: any = 10;


2 tipoDado = "Teste do tipo de dado Any.. ";
3 tipoDado = false;

Let, Var e Const

Nos exemplos apresentados até o momento foi utilizada a palavra reservada let para
definirmos as variáveis, ao invés de utilizarmos a palavra var. Ambas são bastante parecidas,
tendo como diferença a definição do seu escopo. Enquanto o let mantém seus resultados
dentro do bloco onde a variável foi especificada, o var define uma variável como global ou
local para uma função inteira, independente do escopo no qual tenhamos definido o bloco.

Temos ainda a palavra reservada const, que é um complemento para o let e previne a
atribuição de valor a uma variável já declarada (constante).
Observe na Listagem 6 exemplos de uso de let e var. Note que como as variáveis
declaradas por let têm como escopo o bloco no qual são definidas, elas não podem ser
acessadas externamente. Inclusive é possível ter variáveis com o mesmo nome, mas em
escopos diferentes. Essa, no entanto, pode não ser uma boa prática.

1 var a = 6;
2 var b = 15;
3 if (a === 6) {
4   let a = 5;  // este mantém o resultado interno ao bloco
5   var b = 3; //  Em contrapartida, este declara o valor para função, saindo do bloco.
6   console.log(a);  // resultado final = 4
7   console.log(b);  // resultado final = 3
8 }
9 console.log(a); // resultado final = 6
10 console.log(b); // resultado final = 3

Listagem 6. Utilização das palavras reservadas let e var

No exemplo dessa listagem, ao utilizarmos o let dentro de um bloco condicional, o resultado


da variável utilizada, presente na linha 4, é limitado apenas para esse bloco. Definimos que a
variável a tem o valor 5 e está presente dentro do bloco condicional. Já o resultado para a
variável definida como var b recebe o valor dentro do bloco e define ele externamente,
saindo assim do escopo do bloco condicional.

Generics

Uma das principais funcionalidades esperadas de componentes de software é a possibilidade


de serem reutilizados. Linguagens de programação como C# têm em seu conjunto de
ferramentas os tipos genéricos, que são flexíveis para a utilização com qualquer tipo de
dado, mas também bem definidos.

Na Listagem 7 vemos duas formas de definir uma função. Na primeira declaração a função
está pronta para trabalhar apenas com dados do tipo number. Se quisermos trabalhar com
qualquer tipo de dado, podemos optar inicialmente por utilizar a segunda forma, onde o
argumento any pode receber qualquer valor.

1 // função 1 sem generics


2 function Validar(arg: number): number {
3    return arg;
4 }
5 // Função 1 alterada para suportar dados genéricos
6 function Validar(arg: any): any {
7    return arg;
8 }

Listagem 7. Utilizando Generics


Apesar da função definida na linha 6 estar pronta para receber qualquer parâmetro, neste
ponto não temos informações sobre o real tipo de dados como qual estamos lidando, pois a
única informação que teremos de retorno será o any. Precisamos então de uma maneira pela
qual seja possível capturar o argumento e ainda assim deixá-lo genérico. No TypeScript,
semelhante ao que ocorre em C#, podemos utilizar os chamados generics, cuja declaração
utiliza os sinais < e > e dentro deles um nome genérico para o tipo, como vemos a seguir.

1 function Validar<T>(arg: T): T {


2     return arg;
3}

Dessa maneira, temos definida uma variável do tipo T para a função Validar. O T permite que
tenhamos controle sobre o tipo de dado fornecido pela função, de forma a podermos utilizar
essa informação.

A definição dos generics não se aplica apenas a funções, mas também a classes, interfaces,
dentre outros, como no exemplo a seguir:

1 class ClasseGenerica<T> {
2     atributo: T;
3     funcao: (x: T, y: T) => T;
4}

Modules

Como uma das novas definições do ECMAScript 2015, temos introduzido o conceito de
módulos para o JavaScript, e, por conseguinte, para o TypeScript. Estes módulos são
executados dentro do próprio escopo, não sendo possível o seu uso de forma global. Isto
quer dizer que variáveis, funções, classes ou qualquer outra definição, serão visíveis apenas
no módulo onde foram declarados. Em C#, o conceito equivalente é implementado na forma
de namespaces.

Um módulo pode ser utilizado em outro por meio de declarações explicitas de exportação e
importação, declaradas com as palavras reservadas exports e imports entre os arquivos,
respectivamente. Na Listagem 8 temos um exemplo onde criamos um módulo para
validações. Esse módulo contém uma classe que recebe o CEP de um endereço e verifica se
o mesmo é válido

1 module Validacoes {
 class ValidacaoCEP {
2
     ehValido(s: string) {
3
         return s.length === 8 &&
4
numberRegexp.test(s);
5
     }
6
 }
7 }
8 export { ValidacaoCEP };

Listagem 8. Utilização de Módulos


Para utilizar essa a ValidacaoCEP em outras classes, basta realizar a importação, da
seguinte forma:

1 import { ValidacaoCEP } from "./ValidacaoCEP";


2   let validaCEP = new ValidacaoCEP();

Interfaces

Outro ponto importante que merece destaque no Typescript é a possibilidade de criarmos


interfaces personalizadas, que nos ajudam no momento em que precisamos ter consistência
entre os conjuntos de objetos, garantindo assim que os tipos adequados sejam utilizados.
Podemos ver um exemplo simples de sua utilização na Listagem 9, onde apresentamos uma
interface chamada IPessoa e uma classe que implementa esta interface, chamada
PessoaFisica.

1 interface IPessoa {
2     Nome: string;
3     Sobrenome: string;
4 }
5  
6 class PessoaFisica implements IPessoa {
7    Nome : string;
8    Sobrenome : string;
   constructor(public nome, public sobrenome) {
9
       this.Nome = nome
10
        this.Sobrenome = sobrenome;
11
   }
12
}
13
 
14
class ContaCorrente {
15     adicionarCorrentista(pessoa: IPessoa){
16         alert(pessoa.Nome);
17     }
18 }
19  
20 let cliente = new PessoaFisica("Edson",
21 "Dionisio");
22 let conta = new ContaCorrente();
23 conta.adicionarCorrentista(cliente);

Listagem 9. Criação de uma interface com TypeScript

Entre as linhas 1 e 4 definimos a interface IPessoa, que tem apenas duas propriedades. Em


seguida, entre as linhas 6 e 13 criamos a classe PessoaFisica, que implementa essa
interface e define o construtor recebendo valores para os atributos. Já a
classe ContaCorrente, criada entre as linhas 15 e 19 espera, em seu
método adicionarCorrentista, um objeto de tipo compatível com IPessoa. Esse objeto,
declarado na linha 21, por ser do tipo PessoaFisica, pode ser passado como argumento
normalmente na linha 23, uma vez que essa classe implementa a interface esperada.

TypeScript Playground

Na página oficial do projeto há uma seção chamada Playground onde é possível testar
código TypeScript e ver seu equivalente em JavaScript, como ilustra a Figura 1. Ao editar o
bloco do lado esquerdo, automaticamente o outro lado é automatizado e, após concluir as
alterações, basta clicar no botão Run para ver o exemplo em funcionamento.

Figura 1. Visualização do código de uma classe gerada

Na caixa de seleção que pode ser vista na Figura 2 podemos escolher entre uma série de
exemplos predefinidos para visualizar os principais recursos do TypeScript em
funcionamento.

Figura 2. Exemplos pré-definidos


Nas Listagens 10 e 11 podemos ver exemplos de código referentes a criação de uma classe
simples em TypeScript e seu equivalente em JavaScript, respectivamente. Um exemplo
semelhante pode ser obtido ao selecionar a opção Using classes no select da Figura 2.

1class Saudacoes {
2   saudacao: string;
3   constructor (mensagem: string) {
4      this.saudacao = mensagem;
5   }
6   Saudacoes() {
7       return "Olá, " + this.saudacao;
8   }
9}

Listagem 10. Classe criada com TypeScript

Enquanto no TypeScript utilizamos termos como class e constructor, que deixam claro, já à
primeira vista, do que se trata aquele bloco de código, o equivalente em JavaScript utiliza
basicamente funcions para definir todos os elementos. Além disso, para aplicar os conceitos
de orientação a objetos no JavaScript, também é necessário utilizar prototypes, como se vê
na linha 5 da Listagem 11.

1 var Saudacoes = (function () {


2     function Saudacoes(mensagem) {
3         this.saudacao = mensagem;
4     }
5     Saudacoes.prototype.Saudacoes = function () {
6         return "Olá, " + this.saudacao;
7     };
8     return Saudacoes;
9 }());

Listagem 11. Classe criada com JavaScript

Cross-browser

Com a grande diversidade de browsers presentes no mercado, temos muitas vezes


dificuldades na interpretação correta dos arquivos JavaScript, o que torna necessária a
escrita de códigos para Chrome, Firefox, Edge, etc., contendo uma mesma funcionalidade.

Também neste ponto o TypeScript nos auxilia, pois o código que é escrito para uma
determinada funcionalidade é convertido automaticamente para o ECMAScript 3, 5, ou para
o commonjs, garantindo a compatibilidade do JavaScript com todos os browsers que
implementem esses padrões. Assim, ganhamos em produtividade e reduzimos a
necessidade de repetição de código.

TypeScript no Visual Studio

O principal ambiente de desenvolvimento da Microsoft oferece amplo suporte ao TypeScript,


com validação de sintaxe automática em tempo de escrita. De forma semelhante, o editor
mais recentemente lançado Visual Studio Code também suporta o desenvolvimento com
TypeScript, dispondo inclusive do recurso de IntelliSense e code snippets, através dos quais
trechos de código são sugeridos durante a digitação.

A Figura 3 mostra um exemplo do IntelliSense em ação no Visual Studio Code. Observe, no


canto inferior direito, que está selecionada a opção TypeScript, para que o editor possa
oferecer as opções mais indicadas para essa sintaxe.

Figura 3. Edição de código TypeScript no VSCode

Como neste artigo utilizaremos o Visual Studio 2015, veremos a seguir alguns recursos que
esse IDE nos oferece para trabalhar com TypeScript. Para isso, criaremos um projeto
ASP.NET Web Application com o template MVC, o qual chamaremos
de DevmediaTypeScript. Com o projeto criado, clicaremos com o botão direito do mouse
sobre ele no Solution Explorer e buscaremos a opção Add > TypeScript File, como mostra
a Figura 4. Ao nosso arquivo, daremos o nome de TesteDevmedia.
Figura 4. Adicionando um novo arquivo TypeScript

Caso esta opção não esteja sendo apresentada, podemos utilizar as teclas de
atalho Ctrl+Shift+A, para adicionar um novo item, e em Web > Scripts encontraremos os
arquivos necessários, como mostra a Figura 5.

Figura 5. Adicionando um novo item

Com o arquivo criado, perceba que ele já está com a extensão .ts, assim terá acesso a todos
os recursos oferecidos pelo TypeScript.

Começaremos com um exemplo simples, onde teremos apenas uma função para a soma de
dois valores, como pode ser visto na Figura 6.
Figura 6. Função de soma com TypeScript

Com este tipo de arquivo podemos trabalhar com diversas funcionalidades, de igual forma a
outras linguagens de alto nível como o C#, onde podemos ir para as definições das funções
criadas, buscar por referências, etc. Além disso, o IDE nos avisa sobre erros de codificação
ou parâmetros incorretos, como podemos ver na Figura 7. Outro ponto positivo é que o IDE
é capaz de “julgar” os tipos de variáveis, inclusive quando não especificamos os tipos de
dados que iremos utilizar.

Figura 7. Aviso de erro com IntelliSense


Utilizando tipagem estática

Um dos recursos no JavaScript que sentimos falta é a tipagem estática, que apesar de para
alguns cenários ser um ponto positivo dessa linguagem, em outros acaba se tornando
negativo, devido ao fato de deixar a linguagem mais propensa a erros. Para aplicarmos esse
conceito na prática, podemos modificar a função adiciona e modificar em sua assinatura o
tipo dos argumentos esperados, da seguinte forma:

1 function adicionar(x:number, y:number) {


2     return x + y;
3}

Temos no nosso exemplo a solicitação de dois valores numéricos. Caso não houvesse a
tipagem estática, poderíamos tranquilamente passar para essa função dois valores textuais,
por exemplo. Em execução, teríamos como retorno a concatenação dos valores, o que não é
o comportamento esperado neste caso. Graças a esse recurso do TypeScript e seu suporte
no Visual Studio, podemos verificar, em tempo de escrita, que um erro está ocorrendo ao
chamar o método adiciona com argumentos de tipos diferentes dos esperados, como mostra
a Figura 8.

Figura 8. Verificação estática de tipos

Assim como foi visto na Figura 3, no VSCode, o IntelliSense do Visual Studio também nos
oferece diversas sugestões de palavras reservadas durante a digitação ou quando
pressionamos Ctrl+Espaço (Figura 9).

Figura 9. Tipos de dados apresentados com o IntelliSense


Outro ponto positivo que temos a nosso favor ao trabalhar com TypeScript é que para os
tipos de dados mais usados no HTML, ele implementa as interfaces, permitindo que
acessemos diretamente os tipos de elementos HTML, como pode ser visto na Figura 10.

Figura 10. Tipos de elementos HTML

Esse recurso também nos auxilia quando precisamos acessar as propriedades de uma
classe ou interface, listando todos os membros disponíveis, como na Figura 11. Note
também que diferentes símbolos são utilizados para representar os diferentes elementos,
como classes, interfaces, métodos e propriedades.

Figura 11. IntelliSense para membros da classe

Agora que conhecemos os conceitos principais sobre o TypeScript e sua utilização no Visual
Studio, criaremos uma aplicação de exemplo onde o aplicaremos em conjunto com
o AngularJS para montar uma listagem de funcionários.
Projeto TypeScript com AngularJS

Para este exemplo criaremos um projeto do tipo ASP.NET Web Application com o template
Empty, e em seguida devemos excluir o arquivo web.config, pois não precisaremos dele. Na
sequência, utilizaremos o gerenciador de pacotes NuGet para adicionar as bibliotecas
necessárias ao nosso exemplo, que são a AngularJS.Core, AngularJS.Route e
a angularjs.TypeScript.DefinitelyTyped, na qual estão as definições do AngularJS para o
TypeScript. Os pacotes instalados podem ser vistos na Figura 12.

Figura 12. Pacotes para trabalhar com AngularJS

Após a adição dos pacotes, podemos ver que um novo diretório Scripts foi adicionado ao
projeto e, dentro dele, temos todos os arquivos do AngularJS com a extensão “.ts”
necessários ao nosso projeto, como pode ser visto na Figura 13.

Figura 13. Arquivos no diretório scripts


Criando a Interface

Com as bibliotecas instaladas, seguiremos com a criação da interface. Primeiramente


criaremos um novo diretório na raiz do projeto, que chamaremos de app, onde
adicionaremos todo o código da aplicação no decorrer do desenvolvimento. Nesta aplicação,
utilizaremos os serviços do Angular que irão se comunicar com a API REST do back-end,
com o intuito de obter os funcionários registrados. Para começar, definiremos as interfaces
em um diretório separado da lógica de negócio da aplicação. Para isso, criaremos dentro do
diretório app, um novo diretório chamado interfaces. Feito isso, adicionaremos um novo
arquivo TypeScript, chamado interfaces.ts, no qual deveremos adicionar o código
da Listagem 12.

1 module AngularTypeScriptDevmedia.Interfaces {
2    export interface IFuncionariosService {
3        getFuncionarios: () =>
Array<IDadosFuncionario>;
4
   }
5
   export interface IDadosFuncionario {
6
       NomeCompleto: string;
7
       Email: string;
8
       Telefone: string;
9
       Setor: string;
10        Funcao: string;
11        Salario: number;
12    }
13 }

Listagem 12. Criação do arquivo interfaces.ts

Neste primeiro momento, criamos um módulo


chamado AngularTypeScriptDevmedia.Interfaces com duas interfaces: IFuncionariosService,
na qual temos o método getFuncionarios(), que não recebe parâmetros e deve retornar todos
os funcionários cadastrados; e IDadosFuncionario, que recebe todas as informações básicas
dos funcionários. Ao utilizarmos as interfaces, garantimos que não serão passados objetos
aleatórios na nossa aplicação, que podem causar erros inesperados no código.
Precisaremos agora criar um novo arquivo no qual implementaremos a interface de serviços.
Para isso, adicionaremos um novo diretório que chamaremos de services, onde
adicionaremos um novo arquivo TypeScript chamado FuncionarioService, cujo código
encontra-se na Listagem 13.

1 /// <reference path="../interfaces/interfaces.ts" />


2 module AngularTypeScriptDevmedia.Services {
3    export class FuncionariosService implements
4    AngularTypeScriptDevmedia.Interfaces.IFuncionariosService {
5        httpService: ng.IHttpService
6        static $inject = ["$http"];
       constructor($http: ng.IHttpService) {
7
           this.httpService = $http;
8
       }
9
       getFuncionarios = () => {
10
        var listaFuncionarios: Array<AngularTypeScriptDevmedia.Interfaces
11
        .IDadosFuncionario> = [
12
        { NomeCompleto: "Edson Dionisio", Email: "edson.dionisio@gmail.com",
13         Telefone: "81997402800", Setor:
14         "Desenvolvimento de sistemas", Funcao: "Desenvolvedor Júnior",
15         Salario: 2000 },
16         { NomeCompleto: "Marília Késsia", Email: "mkessia@gmail.com",
17         Telefone: "81997402800", Setor:
18         "Educação", Funcao: "Professora", Salario: 3000 },
19         { NomeCompleto: "Caroline França", Email: "carol.dionisio@gmail.com",
20         Telefone: "81997400000",
21         Setor: "Estética e cosméticos", Funcao: "Esteticista", Salario: 5000 },
22         { NomeCompleto: "Renato Nascimento",
23         Email: "renato.nascimento@gmail.com", Telefone:
24         "81996609900", Setor: "Desenvolvimento de sistemas",
25         Funcao: "Desenvolvedor sênior", Salario: 1500 },
        { NomeCompleto: "Mayara", Email: "mayara@gmail.com",
26
        Telefone: "81999999800", Setor:
27
        "Desenvolvimento de sistemas", Funcao: "Tester", Salario: 2500 },
28
        { NomeCompleto: "Benilton Lopes", Email: "benilton@gmail.com",
29
        Telefone: "81999999999",
30
        Setor: "Engenharia", Funcao: "Engenheiro elétrico", Salario: 10000 },
31
        { NomeCompleto: "Artur Oliveira", Email: "arturoliveira@gmail.com",
32         Telefone: "81888888888",
33         Setor: "Desenvolvimento de sistemas",
34         Funcao: "Coordenador de equipe", Salario: 4800 },
35         { NomeCompleto: "Alberto", Email: "alberto@gmail.com",
36         Telefone: "81999999999",
37         Setor: "Desenvolvimento de sistemas",
38         Funcao: "Gerente de negócios", Salario: 8100 },
39         { NomeCompleto: "Marcelo", Email: "marcelo@gmail.com",
40         Telefone: "81999999999",
41         Setor: "Financeiro", Funcao: "Gestor financeiro",
42         Salario: 7500 },
43
44         { NomeCompleto: "Mariana", Email: "mariana@gmail.com",
45         Telefone: "81999999999",
46         Setor: "Recursos Humanos", Funcao: "estagiária",
47         Salario: 1200 }
48           ];
49           return listaFuncionarios;
50         }
51    }
52 angular.module("AngularTypeScriptDevmedia").service("AngularTypeScriptDevmedia
53 .Services.FuncionariosService", FuncionariosService);
54  }
55

Listagem 13. Arquivo FuncionarioService

Nessa listagem estamos encapsulando o serviço criado anteriormente em um novo módulo


que chamamos de AngularTypeScriptDevmedia.Services. Além disso, utilizamos a palavra-
chave export para garantir que o nosso serviço estará disponível para ser chamado a partir
desse módulo. Em seguida, para utilizarmos o serviço, criamos uma nova classe que
implementa a interface IDadosFuncionario e nela adicionamos alguns dados fictícios para
efeito de testes.

No AngularJS existem cinco maneiras diferentes de criarmos um serviço: service (utilizado


no exemplo), factory, provider, value e constant. Cada um dos tipos apresentados possui
seus prós e contras para a criação dos serviços, mas neste exemplo utilizaremos apenas o
primeiro modelo.

Dando prosseguimento, o nosso serviço precisa se comunicar com as APIs de back-end,


devido a isso, utilizamos o $http, um serviço do AngularJS que ao ser adicionado nas
dependências do construtor, irá agir em tempo de execução para realizar a comunicação. O
$inject, apresentado na linha 5, é uma propriedade especial que o AngularJS irá consumir. É
preciso ter certeza de que o $inject tenha sido definido como static, pois o seu valor é um
array de strings e cada um dos arrays é identificado para um serviço em particular, além de
também definir a ordem na qual as strings serão adicionadas ao vetor. O AngularJS realiza a
verificação em tempo de execução para determinar quais são os serviços que precisam ser
injetados. Na linha 25 temos adicionado o código padrão que é encarregado de acrescentar
a nossa classe para o módulo como um serviço.

Finalizada esta etapa, deveremos clicar com a direita no diretório app e em seguida adicionar
o arquivo TypeScript chamado app.module, onde definiremos o módulo do AngularJS que
controlará as rotas da aplicação. Seu código pode ser visto na Listagem 14.

1 /// <reference path="../scripts/typings/angularjs/angular.d.ts" />


2 ((): void => {
3    var app = angular.module("AngularTypeScriptDevmedia", [''ngRoute'']);
4    app.config(AngularTypeScriptDevmedia.Routes.configureRoutes);
5 })()

Listagem 14. Criando o app.module


Na linha 1 dessa listagem referenciamos o arquivo com as definições do AngularJS e na
linha 3 adicionamos a dependência do módulo ngRoute. Na linha seguinte temos a definição
das configurações de rota fornecidas por uma função de referência contida no
namespace AngularTypeScriptDevmedia.Routes, a qual será um novo arquivo TypeScript
cujo código pode ser visto na Listagem 15, ao qual chamaremos de app.routes.ts.

1 /// <reference path="../scripts/typings/angularjs/angular.d.ts" />


2 /// <reference path="../scripts/typings/angularjs/angular-route.d.ts" />
3 module AngularTypeScriptDevmedia {
4   export class Routes {
5     static $inject = ["$routeProvider"];
    static configureRoutes($routeProvider: ng.route.IRouteProvider) {
6
        $routeProvider.when("/home",
7
           {
8
               controller:
9
"AngularTypeScriptDevmedia.controllers.FuncionarioController",
10
               templateUrl: "/app/views/funcionarios.html",
11                controllerAs: "funcionario"
12             });
13         $routeProvider.otherwise({ redirectTo: "/home" });
14   }
15   }
16 }

Listagem 15. Criando a estrutura de roteamento

Nessa listagem estamos configurando uma rota /home que ao ser acessada repassará o
controle para o FuncionarioController e utilizará a view funcionários.html, contida na
pasta /app/views. Já na linha 13 definimos que qualquer outro URL acessado deve ser
redirecionado para a rota padrão /home.

Devemos agora criar a classe FuncionarioController, de acordo com a Listagem 16.

1 /// <reference path="../services/FuncionariosService.ts" />


2 /// <reference path="../interfaces/interfaces.ts" />
3 /// <reference path="../../scripts/typings/angularjs/angular.d.ts" />
4 module AngularTypeScriptDevmedia.controllers {
5    export class FuncionarioController {
6        FuncionariosService:
AngularTypeScriptDevmedia.Interfaces.IFuncionariosService;
7
       static $inject = ["AngularTypeScriptDevmedia.Services.FuncionariosService"];
8
          constructor(FuncionariosService: AngularTypeScriptDevmedia.Interfaces
9
          .IFuncionariosService) {
10
           this.FuncionariosService = FuncionariosService;
11
       }
12
          listaFuncionarios: Array<AngularTypeScriptDevmedia.Interfaces
13           .IDadosFuncionario>;
14        getFuncionariosDestaque = () => {
15               this.listaFuncionarios = this.FuncionariosService.getFuncionarios();
16        }
17    }
18    angular.module("AngularTypeScriptDevmedia").
19 controller("AngularTypeScriptDevmedia.controllers.FuncionarioController",
20 FuncionarioController);
21 }

Listagem 16. Criação do controller de funcionários

Nesta última etapa, criamos o controller e especificamos o serviço como dependência no


construtor, como mostra a linha 8. No controller definimos uma propriedade que chamamos
de listaFuncionarios, presente na linha 11, utilizada para vincular os dados à nossa view.
Além disso, definimos uma função lambda, na linha 12, que será utilizada para
preenchermos a propriedade listaFuncionarios com os resultados da chamada do serviço.

Por fim, criaremos a nossa view, que será responsável por apresentar as informações dos
funcionários. A view que criaremos será chamada de funcionarios.html e seu código ficará
como na Listagem 17.

1 <div class="jumbotron">
2     <ul class="list-group">
3         <li ng-show="Funcionario.listaFuncionarios" class="list-group-item"
4          ng-repeat="devFunc in Funcionario.listaFuncionarios">
            {{ devFunc.NomeCompleto}}
5
            {{ devFunc.Email}}
6
            {{ devFunc.Telefone}}
7
            {{ devFunc.Setor}}
8
            {{ devFunc.Funcao}}
9
            {{ devFunc.Salario}}
10
        </li>
11     </ul>
12     <button class="btn btn-block" ng-
13 click="Funcionario.getFuncionariosDestaque()"
14  >Mostra todos os funcionários</button>
15 </div>

Listagem 17. View de listagem de funcionários

Essa view basicamente utiliza a diretiva ng-repeat para iterar sobre a lista de funcionários do
controller (linha 3) e para cada objeto adicionamos um item na lista (linhas 4 a 9). Na linha 12
o botão faz uma chamada ao método getFuncionariosDestaque do controller, atualizando a
lista e a view.

Com toda esta etapa finalizada, partiremos para o último ponto que é a criação do
arquivo Index.html, o qual é definido na raiz do projeto com o código que vemos na Listagem
18. Mas para que essa página tenha o resultado esperado, precisamos antes instalar o
pacote do Bootstrap pelo NuGet, assim como foi feito com os pacotes do AngularJS. Ao
instalá-lo, será criado o diretório Content com várias folhas de estilo, e o fonts, com os
arquivos de fonte utilizados pelo Bootstrap.
1 <!DOCTYPE html>
2 <html ng-app="AngularTypeScriptDevmedia">
3 <head>
4    <title>Trabalhando com TypeScript e ASP.NET</title>
5    <link href="content/bootstrap.min.css" rel="stylesheet" />
6 </head>
7 <body>
8   <div class="container">
       <div class="page-header">Clique no botão para ver os funcionários
9
cadastrados.</div>
10
       <div class="row">
11
           <div class="col-md-4 col-md-offset-4">
12
               <div ng-view=""></div>
13
           </div>
14
       </div>
15    </div>
16    <script src="scripts/angular.js"></script>
17    <script src="scripts/angular-route.js"></script>
18    <script src="app/app.routes.js"></script>
19    <script src="app/app.module.js"></script>
20    <script src="app/services/FuncionariosService.js"></script>
21    <script src="app/controllers/FuncionarioController.js"></script>
22 </body>
23 </html>

Listagem 18. Criação do arquivo Index.html

Nessa página apenas referenciamos os arquivos CSS e JavaScript necessários para montar
a interface com os recursos do AngularJS. Na linha 12 a div marcada com ng-view carregará
a view funcionários.html quando for necessário, trazendo já os dados do controller. Note que
nas últimas linhas estamos referenciando os arquivos com extensão “.js” e não “.ts”. Isso
ocorre porque, como vimos no início do artigo, o código TypeScript é compilado para
JavaScript, gerando arquivos equivalentes com mesmo nome. Esses arquivos resultantes
são os que serão utilizados pelo browser em tempo de execução.

A utilização de TypeScript em aplicações onde se tem intenso uso de JavaScript permite que
o código seja melhor estruturado, e que as melhores práticas e técnicas de programação
sejam utilizadas. Com o apoio do Visual Studio, é possível aproveitar com maior facilidade
todos os recursos desse superset da linguagem JavaScript, cujo suporte nesse IDE também
tem evoluído a cada versão. Contando também com o suporte a Node.js, por exemplo, é
possível desenvolver aplicações completas, desde o back-end até o front-end utilizado
apenas JavaScript como linguagem principal. Ou, caso seja mais adequado para o projeto,
pode-se aliar os recursos do TypeScript a projetos que já utilizem outra linguagem no lado
servidor, como em Single Page Applications usando Web API e AngularJS. As possibilidades
são muitas e para a maioria delas o Visual Studio poderá suportar o desenvolvimento.

Você também pode gostar