Como vimos no artigo anterior, com TypeScript podemos programar de forma orientada a objetos, criando classes, interfaces, get/set etc, e compilar tudo isso para JavaScript. Neste artigo veremos como criar módulos e separar classes e funcionalidades em arquivos distintos, de forma a tornar o nosso projeto mais organizado.
Para instalar o TypeScript, você precisa ter o Node.js, juntamente com o NPM. Execute o comando
npm install typescript -g
Existem diversas formas de trabalhar com módulos no typeScript, sendo as 3 mais comuns descritas a seguir:
- Combinando tudo em um arquivo somente: Esta é a forma mais fácil de utilizar TypeScript. Primeiro criamos vários arquivos separados, com a extensão
ts
e depois executamos o comandotsc
para juntar tudo em um único arquivo. Veja que todos os arquivos TypeScript serão agrupados, o que pode não ser uma boa prática de programação, principalmente para projetos muito extensos. - Inclusão dinâmica pelo webserver: Neste método todos os arquivos
ts
terão o seu correspondentejs
, na qual serão carregados de forma dinâmica, via ajax. Como estamos utilizando um carregamento dinâmico, precisamos utilizar a biblioteca RequireJS - Inclusão dinâmica pelo node: Nesta forma criamos uma estrutura para ser executada diretamente pelo Node.JS, utilizando o padrão commonjs. Não usaremos este conceito aqui porque queremos ilustrar como utilizar o TypeScript em um site.
Combinando todos os arquivos em um só
Esta forma é a mais simples e pode ser usada na maioria dos seus projetos web. Vamos inicialmente criar a pasta teste1
e nela criaremos duas pastas: src
e build
. A pasta src contém o código fonte da aplicação, os arquivos TypeScript. A pasta build conterá o código JavaScript gerado pelo TypeScript. Na pasta src
, criaremos 3 arquivos:
pessoa.ts
Este primeiro arquivo é uma classe simples, com um parâmetro e o método construtor. A próxima classe será chamada de Aluno
, que irá estender da classe Pessoa
. Como a classe Aluno usa a classe Pessoa (que está em outro arquivo), precisamos importá-la e isso é feito da seguinte forma: ///
. O parâmetro path
é justamente a classe que se deseja referenciar. Então temos:
aluno.ts
Nesta classe referenciamos na primeira linha a classe Pessoa
, informando o nome do arquivo pessoa.ts
. Depois criamos a classe Aluno
, que herda de Pessoa. Na classe Aluno
criamos o parâmetro matricula
, e no seu construtor usamos a palavra super
para referenciar o construtor da classe pai, que neste caso é Pessoa
.
Com as duas classes prontas, podemos finalmente criar o arquivo index.ts
, que é o arquivo principal do projeto.
index.ts
Veja que não é preciso adicionar a classe pessoa. Ela será adicionada na classe aluno
Veja que o arquivo principal faz uma referência a classe Aluno
, do arquivo aluno.ts
. Com os três arquivos prontos, podemos usar o comando tsc
para compilar tudo em um único arquivo. Este comando é executado a seguir.
Nesta imagem usamos o comando tree
do DOS apenas para mostrar que o arquivo script.js
foi criado. O principal comando é o:
Este comando possui como primeiro parâmetro o arquivo ts inicial que neste caso é o index.ts
. O parâmetro --out
indica o nome do arquivo que será gerado pela compilação do TypeScript em JavaScript. Este arquivo é exibido a seguir:
build/script.js
Utilizando módulos
O uso de módulos na aplicação faz com que as classes não pertençam mais ao escopo global, como Pessoa e Aluno pertenciam no exemplo anterior. Vamos fazer uma refatoração no código e adicionar a criação de módulos no escopo da aplicação. Suponha que a classe Pessoa pertença ao módulo “comum” e que a classe Aluno pertença ao módulo “ensino”.
pessoa.ts
Deixamos sublinhado as 2 palavras que são novidade neste código. A primeira é a palavra module
, seguida do nome do seu módulo que neste caso é “comum”. Dentro do módulo “comum” temos a classe Pessoa, e nela usamos a palavra export
que diz ao módulo que esta classe é pública ao módulo. Podemos incluir no módulo classes, variáveis, métodos etc. Para expôr estas classes a outros módulos, usamos export.
A classe Aluno é refatorada para o seguinte código:
aluno.ts
A classe Aluno agora é do módulo ensino
e como novidade temos a referência da classe Pessoa como comum.Pessoa
. Isso é necessário já que estamos modularizando a aplicação. Finalmente, a classe index.ts
é refatorada para:
index.ts
Como novidade temos a chamada da classe Aluno como ensino.Aluno
. Com estas mudanças, podemos executar novamente a compilação:
e obteremos o seguinte resultado:
build/script.js
Módulos em diretórios
Geralmente a organização de módulos é feita em diretórios, para que todos os arquivos não fiquem em somente um único diretório. No caso anterior, poderíamos (na verdade deveríamos) criar os diretórios src/comum
e src/ensino
e reorganizar as classes de acordo com a imagem a seguir.
A única mudança que precisamos realizar no código é no reference
, que deverá ser:
Na classe aluno, como temos que subir um nível para encontrar o diretório “comum”, usamos “../”.
No arquivo index.ts, não precisamos usar “../” pois estamos no mesmo nível do diretório ensino
.
Até este momento todos os módulos estão em um único arquivo de saída, o build/script.js
. Agora desejamos criar uma forma de carregar os módulos sob demanda, ou seja,
ao invés de carregar tudo de uma vez, vamos carregando os arquivos javascript na medida que eles forem sendo requisitados. Para isso precisamos criar uma estrutura um pouco mais complexa, e também precisaremos utilizar um framework qualquer para carregar módulos. Neste caso usamos o Requirejs
.
Criando a estrutura inicial
Crie uma nova pasta e copie os arquivos Pessoa.ts, Aluno.ts e index.ts com a mesma estrutura anterior. Ao invés de criarmos o diretório “build”, crie o diretório “public”, conforme a imagem a seguir.
Redefinido as classes
Ao utilizarmos módulos externos precisamos alterar a forma como referenciamos as classes. Ou seja, não usaremos mais o conforme aprendemos, e não será necessário neste momento definir um módulo. Vamos aos ajustes:
comum/pessoa.ts
O que temos agora é o fim do module
e o uso do export
antes do nome da classe. Na classe Aluno, temos:
ensino/aluno.ts
Alem do fim da palavra module
e do uso do export
, temos uma importante alteração na primeira linha do arquivo aluno.ts. Estamos utilizando a seguinte sintaxe:
Aqui tivemos uma inversão do uso do nome do módulo. Se antes definimos o nome do módulo como “comum” na classe “pessoa”, agora definimos na própria classe “aluno”. Como temos agora o import comum
, podemos usar comum.Pessoa
. O arquivo index.js
é refatorado para:
index.js
Instalando o requirejs
Precisamos instalar o requirejs no projeto, e podemos fazer isso com npm, através do comando npm i requirejs --save
. Este comando irá instalar o “Como vimos no artigo anterior, com TypeScript podemos programar de forma orientada a objetos, criando classes, interfaces, get/set etc, e compilar tudo isso para JavaScript. Neste artigo veremos como criar módulos e separar classes e funcionalidades em arquivos distintos, de forma a tornar o nosso projeto mais organizado.
Para instalar o TypeScript, você precisa ter o Node.js, juntamente com o NPM. Execute o comando
npm install typescript -g
Existem diversas formas de trabalhar com módulos no typeScript, sendo as 3 mais comuns descritas a seguir:
- Combinando tudo em um arquivo somente: Esta é a forma mais fácil de utilizar TypeScript. Primeiro criamos vários arquivos separados, com a extensão
ts
e depois executamos o comandotsc
para juntar tudo em um único arquivo. Veja que todos os arquivos TypeScript serão agrupados, o que pode não ser uma boa prática de programação, principalmente para projetos muito extensos. - Inclusão dinâmica pelo webserver: Neste método todos os arquivos
ts
terão o seu correspondentejs
, na qual serão carregados de forma dinâmica, via ajax. Como estamos utilizando um carregamento dinâmico, precisamos utilizar a biblioteca RequireJS - Inclusão dinâmica pelo node: Nesta forma criamos uma estrutura para ser executada diretamente pelo Node.JS, utilizando o padrão commonjs. Não usaremos este conceito aqui porque queremos ilustrar como utilizar o TypeScript em um site.
Combinando todos os arquivos em um só
Esta forma é a mais simples e pode ser usada na maioria dos seus projetos web. Vamos inicialmente criar a pasta teste1
e nela criaremos duas pastas: src
e build
. A pasta src contém o código fonte da aplicação, os arquivos TypeScript. A pasta build conterá o código JavaScript gerado pelo TypeScript. Na pasta src
, criaremos 3 arquivos:
pessoa.ts
Este primeiro arquivo é uma classe simples, com um parâmetro e o método construtor. A próxima classe será chamada de Aluno
, que irá estender da classe Pessoa
. Como a classe Aluno usa a classe Pessoa (que está em outro arquivo), precisamos importá-la e isso é feito da seguinte forma: ///
. O parâmetro path
é justamente a classe que se deseja referenciar. Então temos:
aluno.ts
Nesta classe referenciamos na primeira linha a classe Pessoa
, informando o nome do arquivo pessoa.ts
. Depois criamos a classe Aluno
, que herda de Pessoa. Na classe Aluno
criamos o parâmetro matricula
, e no seu construtor usamos a palavra super
para referenciar o construtor da classe pai, que neste caso é Pessoa
.
Com as duas classes prontas, podemos finalmente criar o arquivo index.ts
, que é o arquivo principal do projeto.
index.ts
Veja que não é preciso adicionar a classe pessoa. Ela será adicionada na classe aluno
Veja que o arquivo principal faz uma referência a classe Aluno
, do arquivo aluno.ts
. Com os três arquivos prontos, podemos usar o comando tsc
para compilar tudo em um único arquivo. Este comando é executado a seguir.
Nesta imagem usamos o comando tree
do DOS apenas para mostrar que o arquivo script.js
foi criado. O principal comando é o:
Este comando possui como primeiro parâmetro o arquivo ts inicial que neste caso é o index.ts
. O parâmetro --out
indica o nome do arquivo que será gerado pela compilação do TypeScript em JavaScript. Este arquivo é exibido a seguir:
build/script.js
Utilizando módulos
O uso de módulos na aplicação faz com que as classes não pertençam mais ao escopo global, como Pessoa e Aluno pertenciam no exemplo anterior. Vamos fazer uma refatoração no código e adicionar a criação de módulos no escopo da aplicação. Suponha que a classe Pessoa pertença ao módulo “comum” e que a classe Aluno pertença ao módulo “ensino”.
pessoa.ts
Deixamos sublinhado as 2 palavras que são novidade neste código. A primeira é a palavra module
, seguida do nome do seu módulo que neste caso é “comum”. Dentro do módulo “comum” temos a classe Pessoa, e nela usamos a palavra export
que diz ao módulo que esta classe é pública ao módulo. Podemos incluir no módulo classes, variáveis, métodos etc. Para expôr estas classes a outros módulos, usamos export.
A classe Aluno é refatorada para o seguinte código:
aluno.ts
A classe Aluno agora é do módulo ensino
e como novidade temos a referência da classe Pessoa como comum.Pessoa
. Isso é necessário já que estamos modularizando a aplicação. Finalmente, a classe index.ts
é refatorada para:
index.ts
Como novidade temos a chamada da classe Aluno como ensino.Aluno
. Com estas mudanças, podemos executar novamente a compilação:
e obteremos o seguinte resultado:
build/script.js
Módulos em diretórios
Geralmente a organização de módulos é feita em diretórios, para que todos os arquivos não fiquem em somente um único diretório. No caso anterior, poderíamos (na verdade deveríamos) criar os diretórios src/comum
e src/ensino
e reorganizar as classes de acordo com a imagem a seguir.
A única mudança que precisamos realizar no código é no reference
, que deverá ser:
Na classe aluno, como temos que subir um nível para encontrar o diretório “comum”, usamos “../”.
No arquivo index.ts, não precisamos usar “../” pois estamos no mesmo nível do diretório ensino
.
Até este momento todos os módulos estão em um único arquivo de saída, o build/script.js
. Agora desejamos criar uma forma de carregar os módulos sob demanda, ou seja,
ao invés de carregar tudo de uma vez, vamos carregando os arquivos javascript na medida que eles forem sendo requisitados. Para isso precisamos criar uma estrutura um pouco mais complexa, e também precisaremos utilizar um framework qualquer para carregar módulos. Neste caso usamos o Requirejs
.
Criando a estrutura inicial
Crie uma nova pasta e copie os arquivos Pessoa.ts, Aluno.ts e index.ts com a mesma estrutura anterior. Ao invés de criarmos o diretório “build”, crie o diretório “public”, conforme a imagem a seguir.
Redefinido as classes
Ao utilizarmos módulos externos precisamos alterar a forma como referenciamos as classes. Ou seja, não usaremos mais o conforme aprendemos, e não será necessário neste momento definir um módulo. Vamos aos ajustes:
comum/pessoa.ts
O que temos agora é o fim do module
e o uso do export
antes do nome da classe. Na classe Aluno, temos:
ensino/aluno.ts
Alem do fim da palavra module
e do uso do export
, temos uma importante alteração na primeira linha do arquivo aluno.ts. Estamos utilizando a seguinte sintaxe:
Aqui tivemos uma inversão do uso do nome do módulo. Se antes definimos o nome do módulo como “comum” na classe “pessoa”, agora definimos na própria classe “aluno”. Como temos agora o import comum
, podemos usar comum.Pessoa
. O arquivo index.js
é refatorado para:
index.js
Instalando o requirejs
Precisamos instalar o requirejs no projeto, e podemos fazer isso com npm, através do comando npm i requirejs --save
. Este comando irá instalar o“ no diretório node_modules
do seu projeto. Se isso não acontecer, execute antes o comando npm init
para inicializar o repositório npm no projeto. Após instalar o requirejs, copie o arquivo node_modules/requirejs/require.js
para a pasta public/js
. Se você não está confortável com o uso do npm para instalar o requirejs, utilize o seguinte CDN:
Configurando o arquivo index.html
O arquivo index.html
é configurado da seguinte forma:
public/index.html
Neste simples arquivo apenas incluímos o require.js
que foi copiado do node_modules
e usamos o atributo data-main="js/index.js"
para informar o arquivo no qual será carregado inicialmente.
Compilando a aplicação
Aliás este arquivo ainda não foi criado, já que não executamos o comando tsc
. O comando para compilar o JavaScript para que o requirejs possa entendê-lo é o seguinte:
Neste comando indicamos como primeiro parâmetro ./src/index.ts
o arquivo inicial no qual será compilado. O parâmetro --outDir ./public/js/
indica o diretório de saída da compilação, neste caso será o diretório public/js
, o mesmo onde se encontra o arquivo require.js. O terceiro parâmetro --module "amd"
indica a forma como o tsc vai compilar os arquivos, onde AMD significa Asynchronous Module Definition
. Após executar este comando, os arquivos jsvascript serão criados na pasta public/js
conforme a imagem a seguir.
Executando no navegador
Chegou o momento de testar o carregamento dinâmico das classes javascript, e para isso você precisa usar um servidor web. Se você possui um servidor web como o apache, basta copiar a pasta public
para o diretório web e testá-la. Caso negativo, podemos usar o live-server que é facilmente instalado através do node: npm i live-server /g
. Após instalar, acesse o diretório public pela linha de comando e digite o comando live-server
. O navegador será aberto automaticamente e o arquivo index.html
será carregado.
Você verá a mensagem Olá mundo, mas o que estamos interessados é no carregamento dos arquivos javascript da aplicação. Para isso, se estiver no Chrome, tecle F12, navegue até a aba Networking e recarregue a aplicação com F5. Você obterá um resultado semelhante a figura a seguir.
Conclusão
Neste artigo criamos duas formas para utilizar TypeScript no qual os arquivos estão inicialmente separados. A primeira é utilizando o padrão do TypeScript e o ///
e a segunda é usando requirejs
para carregar os arquivos javascript via ajax. Para que você possa se aprofundar ainda mais neste conceito, que é complexo, sugiro a leitura da documentação: https://www.typescriptlang.org/Handbook#modules