Curso de Javascript Completo do iniciante ao mestre - Parte 2

Seção 25 - Expressão Regular

Aula 351 a 355- Introdução / Introdução parte 2 / Introdução parte 3 / Quantificadores e classes de caracteres / intervalos

Regex são padrões utilizados para encontrar, modificar ou validar determinados padrões em strings.
Temos alguns sites para testar expressões regulares. Um deles é Regexr. Para declararmos as regex devemos utilizar as '/expressão_a_procurar/flag'. Entre alguns caracteres temos o '.' que funciona como coringa, e o '[]' que cria um "array" de caracteres que podem ser combinados com a expressão em sequencia (funciona como um 'ou'), '\' é o caractere de escape. Entre as flags temos:
g: global; i: case insensitive; m: multiline; s: single line; u: unicode; y: sticky.
Podemos fazer seleções de caracteres utilizando vários grupos de caracteres '[]' para cada ocorrencia. Podemos repetir essa seleção por quantas vezes for necessário passando o numero de caracters a verificar entre '{}'(quantificador). Para selecionar um limite de seleção podemos colocar no quantificador um valor inicial e um final separado por ','.
Podemos selecionar qualquer número com a opção '\d'.
Quando fazemos uma seleção podemos quantificar com os seguinte sinais: '+' seleciona o valor 1 ou mais vezes; '*' seleciona o valor para 0 ou mais vezes; ? seleciona o valor para 0 ou 1 vez.
Para selecionar todas as letras maiúsculas podemos utilizar a opção '[A-Z]' e as minúsculas '[a-z]' ou '[A-z]' para maiúsculas e minúsculas. A opção '\w' (word) seleciona todos os caracteres alfanuméricos, e o underscore.
Um exemplo até aqui:
/[A-Z]{3}-?\d{4}/g

Aula 356 a 359 - Posição início e posição fim / boundary / Ganancioso ou preguiçoso / caracteres especiais

Quando queremos que a string inicie com uma expressão utilizamos '^'. Qaundo queremos que acabe finalizamos com '$'. Para que essas opções funcionem em todas as linhas utilizamos a flag '/m'.
O '|' funciona como 'ou'.
A opção '\b' limita o início o fim de uma expressão.
A expressão abaixo seleciona todas as tags do tipo <h>, seguidas ou não de textos (id, class, etc) com texto interno que pode ou não ser precedido por espaços (\s) e que termina com </h > (usamos o escape (\) para a '/').
/<th.*?>[\s?\w]+\/h.?>/g
Podemos selecionar grupos de dados para verificar se eles são repetidos em outra ocorrencia. Fazemos isso selecionando a expressão com '()' e apontando a repetição com '\1'. Podemos criar vários grupos e seleciona-los modificando o número no retorno.
A regex é por natureza "gananciosa" ou seja tenta pegar tudo o que estiver após um quantificador ('.', '+', '*'). Para torna-la "preguiçosa" utilizamos o '?' após os quantificadores.
Os caracteres especiais (ç, á, à, é, ã) não são reconhecidos pelas opções '\w' nas regex portanto devem ser declarados.
Para negarmos um conjunto de dados utilizamos o '^' no início do grupo de dados('[]'). Para selecionarmos o inverso dos caracteres utilizamos o operador maiúsculo por exemplo '\W', '\D' e '\S'.

Aula 361 - Expressões regulares com Javascript

Podemos utilizar Expressões Regulares no Javascript de duas formas:
De forma literal com '/RegEx/', ou
Com o construtor new RegExp().
Temos alguns métodos para trabalhar com RegEx:
.test(str), .exec(str)
e com objetos String:
.replace(regex|str, newStr|fn), .match(regex) e .search(regex).

Aula 362 - Validar CEP

Neste exemplo vamos fazer uma lógica com RegEx para testar um número de CEP. Para isso utilizamos no Javascript a expressão:
/^(\d{5}-?\d{3})$/.
Com essa expressão fazemos o teste em um função com o método test() para receber como resultado um booleano.
Não devemos utilizar a flag 'g' quando utilizamos RegEx no JS pois ele tem um comportamento errado. Quando passamos essa flag, o JS tende a intercalar true e false para expressões verdadeiras.

Aula 364 - Desafio: email ou CPF

Resolução do desafio de teste de CPF ou e-mail.

Aula 365 - Resolução Desafio

A resolução o professor ficou igual a minha. Só não lembrei que o endereço de e-mail pode ter '.' ou '-', que foi incluido no grupo de caracteres.

Aula 366 - Datas por extenso

Neste exemplo vamos capturar datas em diversos formatos. Foi criada a seguinte RegEx:
/\d{1,2}\/\d{1,2}(?:\/\d{2,4})?/
Essa expressão seleciona 1 a 2 digitos para dia e mes, separado por '/', e seleciona um grupo de 2 a 4 digitos que pode existir ou não (? no final do grupo) e que ignora o valor do grupo (?: no começo do grupo). Esse '?:' significa que não será capturado o valor do grupo. Quando não utilizamos esse sinal o valor do grupo fica armazenado e quando não existe retorna como undefined.
Quando criamos os grupos '()' o RegEx recupera seus valores individualmente.
Para tratarmos esses valores vamos utilizar o método replace(). Esse método recebe uma RegEx e executa uma função que recebe diversos valores como parametro para cada ocorrencia que seja compatível com a expressão. No nosso exemplo ele apresenta os seguintes valores:
1: valor recuperado pela RegEx;
2: valor do primeiro grupo;
3: valor do segundio grupo;
4: valor do terceiro grupo;
5: posição anterior a localização da RegEx;
6: toda a string verificada.
Com esses valores recuperados podemos apenas selecionar os valores e retorna-los pela função.

Aula 367 - match() e search()

O método search() recebe uma RegEx e retorna a posição da primeira ocorrencia (mesmo com a flag 'g')(OBS: nesse caso não tivemos o erro da flag).
Quando o search() não encontra nenhum resultado ele retorna '-1'.
O método match() retorna um array com diversas informações da RegEx semelhante a função do método replace() porém apenas quando não utilizamos a flag 'g'. Quando utilizamos a flag 'g' ele retorna em cada posição do array o objeto encontrado pela RegEx. O método match() é muito custoso em recursos do sistema e deve ser evitado.

Aula 368 - exec()

O método exec() quando executado em modo normal retorna um array com os dados da mesma forma que o método match(). Já com a flag 'g' ele retorna os arrays conforme a execução um após o outro. Isso ocorre pois temos no regex um atributo lastIndex que armazena a posição da última expressão encontrada até que o retorno seja 'null' e o lastIndex receba o valor '0'.

Aula 369 - new RegExp()

Quando precisamos passar um valor de consulta em uma RegEx que não seja fixo não conseguimos fazer através do modo literal pois ele não permite a passagem de variáveis. Nesse caso podemos utilizar o método RegExp('expressão', 'flag').
Para passarmos as opções com o RegExp() precisamos adicionar uma '\' aos operadores (\\d, \\w, etc).

Aula 370 - Desafio: URI

Minha resolução para o desafio de criar um objeto com as opções de uma URI de busca do google separando cada opção como um para chave/valor.

Aula 371 - Resolução Desafio: URI

Na resolução o professor fez basicamente a mesma ciosa que eu, porém ele facilitou a origem de dados (onde eu quebrei a cabeça para entender). Note que dentro dos grupos da RegEx ('[]') não precisamos escapar os caracteres.

Aula 373 - Exercício proposto: Destacar texto

Consegui resolver o desafio. O primeiro problema foi lembrar o método split() passando a RegEx e depois utilizando o join() para remontar o texto. O outro problema foi que estava utilizando o innerHTML e o aplicativo só funcionou depois que passei a utilizar o innerText. Atenção para a seleção dos elementos. Primeiro utilizei o querrySelectorAll porém ele gera uma NodeList que não é manipulável. Mudei para getElementsByTagName() que gera uma HTMLCollection.

Aula 374 - Resolução: Destacar texto

Na resolução dom desafio foi utilizado o método que eu estava tentando lembrar Array.from() combinado com o map(). Outro ponto foi a utilização do innerText ao invés do textContent. No mais foi utilizado o método replace() em vez do exec() como eu utilizei.
Todo esse processo entretanto tem ainda um problema. Quando temos tags HTML no meio do texto pesquisado elas são sobrepostas pelo valor que retornamos, ou seja, remove a tag HTML original que estava no meio do texto. Para ajustar isso vamos utilizar o innerHTML ao invés do innerText, em seguida criamos um array para manter o texto original e fazer as mudanças, como eu tinha pensado em fazer na minha resolução.

Seção 26 - Módulos no node e tooling

Aula 375 - CommonJS

Inicialmente vamos inicializar um projeto npm com o comando:
$ npm init -y
Após iniciado o projeto é criado o arquivo package.json que contém as configurações do projeto nodeJS. Podemos incluir novos frameworks com o comando:
$ npm install aplication --save-dev
A flag --save-dev (ou -D) instala o módulo apenas no modo de desenvimento e não será incluido no modo de produção.
O nodeJS tem alguns módulos nativos. Para utiliza-los precisamos declara-los em uma variável com o parametro require('nome_do_modulo').
Um dos módulos é o fs (File System), que permite a manipulação de arquivos.
Com o módulo fs declarado podemos por exemplo criar arquivos com o comando:
fs.writeFile('nome_do_arquivo', 'dados_a_gravar', função_de_callback.
Quando trabalhamos com commonJS utilizamos o require sempre que formos importar dependencias.
Para esse projeto instalamos a dependencia node-emoji.

Aula 376 / Aula 377 - module.exports / module.exports sem colisão de nomes

Podemos criar variáveis e funções em módulos e exportá-las com o método module.exports. Esse método exporta um objeto com os dados no formato chave: valor, ou seja podemos acessar o valor através do nome da variável criada para importar o módulo seguida de '.' e o nome da propriedade a ser acessada (que é o nome da variável que exportamos).
Quando exportamos uma variável com a sintaxe:
module.exports.variável = valor
estamos incluindo em um objeto vazio o par chave/valor. Esse valor pode ser acessado tanto por module.exports quanto por exports (os dois fazem referencia ao mesmo ponto na memória).
Já quando atribuimos ao module.exports um objeto:
moduel.exports = {variável: atributo}
teremos o acesso por module.exports, entretanto o exports terá como valor um objeto vazio '{}'.
Quando passamos uma função através do module.exports o valor que vamos passar será o valor retornado pela função do module.exports, e não o valor executado da função.
Quando utilizamos o CommonJS não temos problemas com colizão de nomes pois as variáveis de cada módulo ficam isoladas no escopo local, e os módulos que são exportados podem ser atribuidos a nomes que serão acessados apenas no escopo do arquivo que faz a importação, e seus valores são nomes de atributos independentes para cada import.

Aula 378 / Aula 379 - ESM no node / Esport sem colisão de nomes

A partir do NodeJs versão 14 é possível trabalhar com ES15.
Para usar ESM (EcmaScriptModule) no NodeJs precisamos informar que estamos utilizando esse padrão caso contrário receberemos a seguinte mensagem de erro:
Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
Portanto podemos fazer isso de duas maneiras alterando a extensão do arquivo ou incluindo o 'type' no package.json.
Um dos problemas em usar ESM é em relação ao acesso a duas variáveis do sistema NodeJs que não funcionam nesse modo. São elas a __dirname e __filename.
Quando temos duas variáveis exportadas que tem o mesmo nome podemos importa-las com nosmes diferentes, bastando para isso indicar no momento da importação da seguinte forma:
import { nome_da_variavel_importada as nome_da_variavel_local } from 'arquivo_de_origem'

Aula 380 a Aula 382 - babel: códigos cross-browser / Iniciar babel na stack de desenvolvimento / babel.config

Entendendo a utilização do Babel para fazer o ajuste e a conversão de código para utilização em plataformas mais antigas. Fazendo testes no try out do site Babel.
Após iniciar o projeto Node vamos fazer as instalações dos pacotes do Babel. Vamos instalar 3 módulos na versão definida para evitar incompatibilidades. O comando de instação é o seguinte:
$ npm i --save-dev @babel/[email protected] @babel/[email protected] @babel/[email protected]
Em seguida criamos dois diretórios src e dist sendo que o primeiro irá armazenar o código que nós iremos criar e o segundo o código pronto para distribuição, ou seja, transpilado com o Babel.
Para fazer a conversão dos arquivos utilizamos o comando:
$ npx babel origem -d destino
Com esse comando as mudanças ficam estáticas, ou seja precisamos refazer a operação sempre que alterarmos o arquivo de origem. Para evitar isso podemos utilizar a flag -w ou --watch que faz a atualização automática do código de saida.
Para que o Babel faça as conversões do código digitado precisamos setar a 'env'. Podemos fazer isso com as pré definições do Babel através do comando:
$ npx babel src -d dist --presets=@babel/env Outra forma é criando um arquivo babel.config.json de configuração onde podemos especificar quais os navegadores que desejamos utilizar ou ainda o percentual de compatibilidade que desejamos. Um exemplo desse arquivo é o que segue:
{ "presets": [ [ "@babel/preset-env", { "targets": { "chrome": "58", "ie": 11 } } ] ] }
Em seguida criamos uma rotina mais elaborada no JS com async/await, fetch e try/catch. Nesse caso tivemos alguns erros na criação do arquivo transpilado pois precisamos de outras configurações no arquivo babel.config.json. Inserimos essas tres linhas:
"useBuiltIns": "usage", "modules": false, "corejs": 3
Essa alteração é para que o código convertido importe as bibliotecas necessárias para executar as funções criadas pelo Babel. O modules é para que o código trabalhe com o import ao invés do require.
Mesmo assim, com isso ainda não resolvemos o problema de compatibilidade de navegadores antigos pois como ficou o código após o ajuste do Babel ainda teremos incompatibilidades como por exemplo a necessidade de utilização do module. Para resolver isso vamos utilizar o WebPack que é um empacotador, que agrega ao código, tudo que é necessário para que ele seja executado, sem a necessidade de utilizar arquivos externos através de require ou import

Aula 383 - configurar webpack

O Webpack faz uma organização dos arquivos do projeto e suas dependencias de modo que tenhamos apenas 1 arquivo de cada tipo, evitando que na aplicação que vai para produção, tenhamos diversos arquivos para cada função.
Para instalar o webpack digitamos o seguinte comando:
$ npm install --save-dev [email protected] [email protected]
Além da instalação do webpack precisamos instalar o babel-loader que vai ajudar na conversão feita pelo webpack. Instalamos com:
$ npm install --save-dev [email protected]
Em seguida criamos o arquivo de configuração do webpack. A criação desse arquivo é bastante complicada e precisa ser estudada conforme a necessidade. Como acho que não vou precisar disso no futuro não vale a pena descrever aqui. O arquivo a ser criado é webpack.config.js e ele utiliza entre outra coisas a propriedade __dirname mencionada acima, além de RegEx para selecionar arquivos a serem verificados ou excluidos.
Após isso executamos o webpack com o comando:
$ npx webpack
Com os ajustes feitos no arquivo de configuração ainda verificamos que faltou instalar outro componente do babel:
$ npm install @babel/[email protected] --save-dev
Após isso uma nova mudança no arquivo de configuração e novamente executamos o webpack.
A próxima instalação é do core-js que pode ser visto no import do arquivo gerado no Babel.
$ npm install [email protected]
Em seguida importamos o core-js no arquivo original. O fetch também não é (ou era) compatível portanto intalamos uma nova biblioteca axios.
npm install [email protected]
O axios é um cliente HTTP baseado em promise e substitui o fetch e as outras formas de requests HTTP.

Aula 384 - webpack refatoração

Com o arquivo gerado pelo webpack podemos remover os eval colocando uma nova configuração no webpack.config que é sugerida no arquivo gerado: devtool: false. Após isso temos um novo arquivo sem os métodos eval. Desse modo ao verificarmos a aplicação no DevTools do Chrome somos direcionados para a linha de código do arquivo gerado pelo webpack. Entretanto para fins de depuração não conseguimos localizar o local da rotina no código bruto. Para podermos localizar as instruções no código podemos setar a opção devtool: "source-map". Esse procedimento gera um arquivo '.map' que mapeia os arquivos de origem.
PAra reduzi um pouco o tamanho do arquivo gerado pelo webpack podemos fazer o import do core-js com a opção '/stable'.
Outra alteração é alterar a configuração do webpack de mode: "development" para mode: "production".

Seção 27: Typescript: introdução

Aula 385 - Introdução

Typescript é uma linguagem que adiciona tipagem estática ao javascript. Adiciona novas features no javascript que nos permite definir tipos para variáveis, parâmetros, retornos de funções, etc. Seu principal objetivo é evitar mudanças inesperadas no código por alteração no tipo.

Aula 386 / Aula 387 - Preparação e instalação / configuração

Para iniciar um projeto em Typescript primeiramente inicializamos um projeto npm. Em seguida instalamos o typescript com o comando:
$ npm install [email protected] -D
Os arquivos em typescript tem aa extensão .ts e não saõ intepretados nativamente pelos motores JS (pode ser executado nativamente pelo deno).
Para transpilar os arquivos .ts utilizamos o comando:
$ npx tsc nome_do_arquivo
Caso o typescript esteja instalado globalmente podemos executar o tsc diretamente sem o npx.
Quando fazemos alguma ação ilegal no typescript recebemos uma mensagem de erro e não conseguimos concluir a transpilação do arquivo.
Podemos ver as opções do tsc com o comando:
npx tsc --help
Precisamos configurar alguma opções para o typescript e fazemos isso com um arquivo de configuração. Para criar o aruivo de configuração padrão do typescript utilizamos o comando:
$ npx tsc --init
Essa opção cria uma arquivo tsconfig.json onde podemos ajustar as opções do tsc.
Entre os atributos que podemos configurar nesse arquivo temos o outDir que especifica o diretório de saída do arquivo .js gerado e rootDir que especifica a origem do arquivo .ts.
Mesmo com essa configuração do rootDir se criarmos arquivos .ts fora do diretório especificado ela fará a conversão. Para especificar quais os diretórios que devem ser observados para conversão devemos criar no arquivo de configuração uma propriedade "include": [diretórios_a_observar].

Aula 388 - Tipos primitivos e array

Podemos declarar os tipos de variável em TS descrevendo com :tipo_de_variável. Essa declaração não é obrigatória mas faz parte da sintaxe. Os tipos podem ser:
string, number, boolean.
O mesmo podemos fazer com arrays declarando nome_da_variável:tipo_de_variável[].
Podemos criar arrays no modo generic com a sintaxe nome_da_variavel: Array<tipo_da_variavel>

Aula 389 a Aula 395 - Objetos / tuplas / enum / any vs unknown / void vs never / null e undefined / union types

Criamos objetos definindo seus atributos e o tipo esperado para cada um, da seguinte forma:
let nome_do_objeto: { atributo1: tipo, atributo2: tipo, ... atributo_n: tipo }
Uma vez criados os atributos do objeto, não podemos fugir da estrutura definida, ou seja, não podemos criar novos atributos que não tenham sido declarados na criação do objeto, bem como não podemos criar o objeto sem as propriedades definidas. Para que um atributo não seja obrigatório podemos incluir o sinal '?' após o nome do atributo. Isso não muda o tipo do valor. A ordem que as propriedades são declaradas não importam.
Podemos criar objetos vazios sem definir nenhum atributo que aceitaram qualquer valor, porém isso deixa de ser interessante para a utilização do TS.
As tuplas não existem no JS. As tuplas são arrays com o numero e tipo de valores definidos, ou seja, não aceitam mais valores que o especificado, nem tipos diferentes dos definidos para cada indice.
O enum permite que criemos variáveis fixas no sistema que podem ser acessadas como propriedades do objeto criado.
Quando declaramos parametros em uma função sem especificar o seu tipo, por padrão o TS irá retornar um erro dizendo que o tipo implícito é any. Podemos evitar essa mensagem de erro alterando as configurações do tsconfig.json passando false no parametro:
"noImplicitAny": false
Nesse caso o tipo dos parametros passará a ser any (ou seja qualquer coisa). Isso deve ser evitado pois uma vez que estamos utilizando TS não queremos esse tipo de situação.
Quando isso acontece, podemos passar para os parametros o tipo unknown. Nesse caso o erro não será mais nos parametros mas sim no retorno da função pois ela espera uma definição do tipo antes do return. Verifique que o erro é sanado quando fazemos um teste lógico de typeof nos parametros.
O tipo void é utilizado em funções para indicar que elas não retornam nenhum valor. Essa função se executada vai retornar undefined. Podemos indicar isso na sintaxe da função:
function nome_da_função(param: tipo, param: tipo) : void { corpo_da_função }
Nesse caso ela não vai aceitar retorno.
Já a função never indica que ela nunca vai retornar nada (nem undefined).
Temos ainda dois tipos null e undefined.
Nos union types podemos ter dois tipos em uma variável, por exemplo number | undefined (quando declaramos uma variável que é opcional com o sinal de ?). Podemos declarar que uma mesma variável pode ter dois tipos utilizando o sinal de union '|'. Se, por exemplo declaramos que determinada variável deve ser de um tipo | null, ela não pode ter seu valor omitido. Ela deve ser ou do tipo definido ou necessariamente null.

Aula 396 a Aula 399 - alias / intersection / function / remover redundancias

Alias funciona como uma forma de facilitar a atribuição de tipos a variáveis. Quando temos variáveis com diversos tipos podemos criar um type com uma estrutura de tipos que pode ser definida para quaisquer outras variáveis.
Podemos utilizar o alias também para definição de atributos e tipos de um objeto.
Podemos também passar valores como se fosse o enum.
O intersection é representado pelo '&' e indica a interseção ou união de dois conjuntos de tipos. Ele permite que tenhamos um objeto que agregue ao mesmo tempo os atributos de dois conjuntos de alias.
Podemos tipar funções definindo os tipos dos parametros e do retorno, da seguinte forma:
function add(x: number, y: number): number {
return x + y
}

Podemos declarar os tipos em arrow functions e podemos declarar uma arrow function com os tipos que recebe uma arrow function com os valores:
const sub: (x: number, y: number) => number = (x, y) => x - y
Outro exemplo de tipagem de funções é o apresentado na aula. Primeiro criamos um alias com uma arrow function que define o tipo de dados a serem tratados. No exemplo a função irá tratar todos os elementos de alias 'User', que faz parte de uma intersection com 'Admin'. Essa função em pprincípio retornaria um erro pois o elemento a ser testado não faz parte do 'alias' 'User'. Para podermos testar todos os 'User' informamos que o parametro 'user' deve ser tratado as 'UserAdmin'. Dessa forma a função vai avaliar todos os 'User' independente de eles fazerem parte da intersection ou estiverem apenas no grupo 'User'.
Na aula a função foi tipada declarando que o parametro esperado pela função seria user: User. Na atribuição da função foi passado o parametro user: User novamente o que não é necessário pois quando tipamos a função já foi declarado o parametro.
Esta operação de definir um tipo ou parametro como parte de outro se chama assertion.
A assertion é geralmente utilizada em manipulação do DOM. Quando fazemos referencia a um elemento do DOM com document o TS vai automaticamente aplicar o sinalizador '?' para dizer que seu tipo pode ser null, ou seja ele pode não receber uma resposta. Quando queremos determinar que existe certeza na resposta podemos dizer que o elemento deve ser considerado como as(HTML...) ou seja que ele deve ser interpretado como um elemento do HTML (as opções são demonstradas pelo VSCode). Quando definimos como qual elemento HTML ele vai se comportar o valor do evento monitorado já passa automaticamente a ser interpretado como um evento.

Aula 401 - testar no terminal

Para testar arquivos TS no terminal podemos executar o transpilador com o comando:
$ npx tsc
e em seguida executar os arquivos '.js' gerados com o node.
Outra opção é instalar o pacote ts-node:
$ npm i [email protected]
Com o ts-node instalado podemos executar os arquivos '.ts' diretamente com o comando:
$ npx ts-node arquivo.ts
Esse procedimento é um pouco mais demorado mas evita que se transpile todos os arquivos.

Aula 402 - testar no browser (com webpack)

Para testarmos aplicações escritas em TS no browser, sem fazer a transpialção podemos utilizar o webpack. Para isso precisamos instalar os seguinte módulos:
$ npm i webpack webpack-cli ts-loader
Não fizemos essa instalação pois precisariamos fazer todas as configurações do webpack. Ao invés disso aproveitamos a configuração que já tinhamos do webpack com o babel e incluimos as configurações para utilizar o ts-loader. Instalamos naquele projeto o typescript e alteramos as denominações dos arquivos para serem carregados.

Aula 403 - Exercício proposto: Conversor de polegadas para centímetro

Minha resolução para conversor polegadas para centimetro.

Aula 404 / Aula 405- preparação do ambiente / resolução: converter polegadas para centimetros

Explicação sobre o projeto. Informações sobre o SASS, e inicialização do projeto com npm install e npm run build.
Quando trabalhamos com TS temos que verificar como os parametros são passados e qual sua tipagem. Quando monitoramos o evento diretamente no listener o this é o elemento monitorado. Entretanto quando criamos uma função externa o this deixa de fazer referencia ao elemento e o valor recebido deixa de ser um event, ambos são interpretados com o tipo any.
Para que o evento passe a ser considerado como tal, podemos criar uma alias para a função especificando que ela recebe como parametro um evento. Isso não resolve o problema do this. Para resolver esse problema passamos também no alias a informação que o this é o elemento desejado (no caso HTMLInputElement).
Feito isso é apenas a manipulação de string para numero e numero para string e as funções de fórmulas.

Seção 28: Typescript: Classes

Aula 406 a Aula 411 - Preparação do ambiente / public, readonly e private / extends e protected / classes abstratas / getters e setters / lista de objetos

Nessa aula iniciamos o nodeJS e instalamos os pacotes TS e ts-node-dev:
$ npm init
$ npm install [email protected] [email protected] --save-dev
Para executar o ts-node-dev com modo de atualização automática, utilizamos a flag --respawn.
No TS basicamente a declaração de classes segue o mesmo padrão do JS, com a diferença que no TS declaramos os tipos dos atributos.
Podemos criar as classes do modo mais longo declarando o tipo do atributo, e passando o valor em parametro no construtor para o atributo ou podemos passar o atributo diretamente no parametro do construtor com o modificador de acesso public nos parametros do constructor().
Quando declaramos o modificador public podemos alterar os valores do atributo de qualquer local do programa. Para impedir que alteremos o valor dos atributos podemos utilizar o modificador readonly que só permite ler os valores.
Já o modificador private não permite que acessemos os atributos nem os modifiquemos fora da classe. Do mesmo modo o protected não permite o acesso as propriedades, mas difere do private quando utilizamos as heranças.
Para visualizar os atributos no modificador private precisamos criar métodos para que possamos acessa-los (getters/setters?).
Podemos trabalhar com heranças entre as classes com o extends. Quando utilizamos o extends precisamos criar o método super() dentro do constructor().
Quando temos classes herdadas de classes com o modificador de acesso private, não temos acesso a essa propriedade mesmo que na classe que a extende. Para podermos passar o acesso as classes filhas devemos alterar o modificador para protected. Com o modificador protected, as classes filhas tem acesso aos atributos da classe pai. Porém quando fazemos isso temos acesso irrestrito aos atributos da classe pai pela classe filha, inclusive de alterar seu valor.
Para proteger um atributo do tipo protected de ser editado pela classe filha podemos indicar a propriedade readonly junto com a protected (o modificador protected deve vir antes do readonly).
Podemos passar esses modificadores também na construção de classes de modo mais curto.
Podemos definir na criação da classe a propriedade abstract. Com essa propriedade a classe deixa de poder ser instanciada e pode apenas ser extendida por outra classes.
Podemos manipular os atributos de classes private e protected com os getters/setters. Essas funções são métodos criados na classe que permitem a alteração de forma protegida dos dados da classe. Para isso utilizamos os operadores get e set para criação dos métodos.
Podemos criar listas de objetos bastando para tal criar a propriedade e passar o objeto como argumento. Quando fazemos isso passando outra classe como argumento o TS na verdade não espera receber os elementos que pertencem aquela classe, mas sim objetos que tenham as mesmas propriedades e métodos da classe base. Dessa forma se passarmos um objeto novo que possua essas mesmas características o código será aceito.
Quando criamos arrays(listas) de objetos sem alterar o modificador podemos alterar seu conteudo simplesmente atribuindo um novo valor. Podemo evitar isso alterando o modificador para readonly entretanto ainda podemos mudar isso atribuindo por exemplo um valor '0' para o objeto.array_objetos.length. Nessa situação o array vai passar a ser vazio pois seu tamanho é '0'. Lembrando que arrays são apontamentos em memória e não valores, portanto a manipulação de propriedades e métodos de array podem modificar os dados mesmo com o modificador readonly.
Para evitar esse tipo de manipulação podemos alterar essa propriedade para private. Quando criamos atributos private é comum colocarmos um '_' na frente do nome do atributo. Alterado o modificador para private caso criemos um getter no modo convencional esse novo método vai permitir que façamos as mesmas alterações que sem o private. Para corrigir isso podemos passar um spread operator no retorno do getter que vai retornar uma cópia do array e não o array original. Entretanto cada vez que ele for executado será gerada uma nova cópia o que pode compremeter o uso de memória. Nesse caso criamos um novo atributo temporário que irá armazenar a cópia dos valores do array original mas que irá zerar o seu valor a cada chamada, de modo que não gere diversas cópias do array em memória. A desvantagem é que teremos dois arrays no objeto principal (o original e o temporário)

Aula 413 a Aula 415 - Interfaces vs classes abstratas / Duas interfaces / Interfaces vs type alias

Quando utilizamos o extends em uma classe e utilizamos o método super() esse método é uma referencia direta a classe pai. Portanto podemos, por exemplo, utilizar o comando super.método_da_classe_pai. Quando criamos uma classe abstract ela não pode ser instanciada e as classes que extends a classe pai recebem os seus atributos e métodos. Podemos criar métodos ou atributos abstratos, e esses métodos devem ser construidos nas classes filhas.
Quando fazemos a conversão de uma arquivo TS para JS, o abstract deixa de ser válido, ou seja, uma classe abstrata no TS pode ser instanciada no JS.
Podemos criar também ao invés de classes abstract padrões do tipo inteface. O interface á um 'contrato' que determina para a classe quais elementos ou estrutura ele deve ter. As interface não utilizam o extends mas o implements para serem utilizadas pelas classes filhas. Esse tipo de elemento não precisa do método super(), bastanto que se passem os atributos e métodos na classe implementada.
Podemos ainda utilizar os objetos criados com o implement para criar objetos sem ser instanciados com o new.
Podemos implemetar mais de uma classe dom tipo interface, o que não é possível com o extends.
Quando geramos o arquivo JS não teremos mais as interface pois elas só existem em tempo de compilação e não em runtime. Resumindo as classes, abstratas ou não são levadas para o código final que será utilizado em produção. Já as interfaces não. As interfaces não aceitam modificadores de acesso e não aceitam implementação de métodos, apenas podemos declarar que a classe que implementar a interface deverá implementar também os métodos.
Por fim as interface se assemelham aos type alias. Se substituirmos o interface por type teremos o mesmo resultado. As principais diferenças entre interface e type alias é que a primeira permite que se criem mais de uma classe com o mesmo nome, já o type acusa duplicidade de identificador.
Outra característica é que a interface não permite criarmos tipos primitivos (declarar o tipo da variável), e também não aceita a utilização de '|' (union) ou '&' (intersection). Outra diferença é na sintaxe de declaração de funções conforme exemplo.

Aula 384 - webpack refatoração