Introdução
O arquivo tsconfig.json especifica as opções de compilação usadas pelo compilador TypeScript, que aplica verificações ao nosso código e determina se alguma dessas verificações falha. Essas opções incluem para qual versão do JavaScript nosso código TypeScript será compilado, qual deve ser o diretório de saída e se devemos ou não permitir arquivos de origem JavaScript no diretório do projeto.
Neste artigo, iremos dê uma olhada em profundidade em algumas opções avançadas do compilador e algumas outras opções que nos ajudam a encontrar problemas em potencial em nossa base de código TypeScript. Um conhecimento profundo dessas opções do compilador e do que faz com que o código falhe nas regras de verificação estrita nos ajudará a evitar erros comuns ao construir aplicativos TypeScript.
Especificamente, este artigo cobrirá as seguintes opções:
Arquivos tsconfig.json aninhados strictPropertyInitialization noImplicitThis noImplicitReturns strictNullChecks
Arquivos tsconfig.json aninhados
O compilador TypeScript pode fazer referência a um arquivo tsconfig.json em outro diretório ao compilar o código no diretório atual.
Este recurso é útil se quisermos fazer referência a uma opção do compilador ao executar tsc em um diretório específico. O arquivo tsconfig.json usa a opção”referências”para essa finalidade.
Como exemplo dessa configuração aninhada, considere a seguinte árvore de origem:
├── dist └── src ├─ ─ tsconfig.json ├── backend │ ├── index.ts │ └── tsconfig.json └── frontend ├── index.ts └── tsconfig.json
Aqui, temos um arquivo tsconfig.json no diretório src do projeto, bem como em dois subdiretórios chamados frontend e backend. Ambos os subdiretórios contêm um arquivo tsconfig.json e um arquivo TypeScript denominado index.ts.
O arquivo tsconfig.json no diretório src do projeto é o seguinte:
{“compilerOptions”: {“target”:”es5″,”módulo”:”commonjs”,”rootDir”:”.”,”outDir”:”../dist/”,},”arquivos”: [],”referências”: [{“path”:”./backend”}, {“path”:”./frontend”}]}
Aqui, especificamos a propriedade outDir para gerar todas as saídas JavaScript no diretório dist, seguido pela configuração de caminhos de referência para ambos os subdiretórios.
Todo o projeto pode ser compilado com o seguinte comando:
tsc–build src
Vamos dar uma olhada no arquivo tsconfig.json no diretório backend, como segue:
{“compilerOptions”: {“rootDir”:”.”,”outDir”:”../../dist/backend”,}}
Aqui, especificamos a propriedade outDir para gerar toda a saída do JavaScript no diretório dist.
Isso significa que o TypeS O compilador cript irá enviar todos os arquivos JavaScript neste diretório para o diretório dist, que está dois níveis de diretório acima.
O subdiretório frontend pode ser construído independentemente usando o seguinte comando:
tsc–build src/frontend
Vamos dar uma olhada no arquivo tsconfig.json no diretório de back-end:
{“compilerOptions”: {“rootDir”:”.”,”outDir”:”../../dist/frontend”,},”reference”: [{“path”:”../backend”}”composite”: true]}
Da mesma forma, especificamos a propriedade outDir para gerar todas as saídas JavaScript neste diretório para o diretório dist, que está dois níveis de diretório acima, seguido pela configuração do caminho de referência para o subdiretório backend.
Anote essas informações em os documentos do TypeScript : “Os projetos referenciados devem ter a nova configuração composta ativada. Esta configuração é necessária para garantir que o TypeScript possa determinar rapidamente onde encontrar as saídas do projeto referenciado. ”
Além disso, o subdiretório de backend pode ser construído independentemente usando o seguinte comando:
tsc–build src/backend
strictPropertyInitialization
Quando ativada, a opção do compilador strictPropertyInitialization garante que todas as propriedades dentro de uma classe sejam inicializadas corretamente.
Vamos considerar a seguinte definição de classe:
classe NoInitProperties {a: número; b: corda; }
Aqui, temos uma classe chamada NoInitProperties, que possui duas propriedades, chamadas a do tipo número eb de tipo string. O código acima irá gerar os seguintes erros:
erro TS2564: A propriedade’a’não tem inicializador e não está definitivamente atribuída no erro do construtor TS2564: A propriedade’b’não tem inicializador e não está definitivamente atribuída no construtor
Esses erros estão sendo gerados porque as propriedades aeb da classe não foram inicializadas.
Resolvendo problemas de strictPropertyInitialization
Existem quatro maneiras de corrigir esse código.
O primeiro método é comumente usado para corrigir esses erros e usa um construtor:
class NoInitProperties {a: number; b: corda; construtor (b: string) {this.a=5; this.b=b; }}
Aqui, definimos uma função construtora com o parâmetro b do tipo string. Dentro do construtor, atribuímos o valor do parâmetro b à propriedade b interna. Além disso, atribuímos o valor da string”letter”à propriedade chamada a. Com este construtor no lugar,
o erro será corrigido porque ambas as propriedades agora foram inicializadas corretamente.
O segundo método é usar uma união de tipo:
class NoInitProperties {a: number | Indefinido; b: string | Indefinido; }
Aqui, o tipo de união é usado para adicionar o tipo indefinido às propriedades a e b. Com isso, o compilador sabe que estamos cientes de que essas propriedades podem ser indefinidas, o que nos permitirá lidar com as consequências por nós mesmos.
O terceiro método que podemos usar para corrigir esses erros é usar o definitivo operador de asserção de atribuição:
class NoInitProperties {a !: número; b !: string; }
O! operador adicionado após cada propriedade informa ao compilador que estamos cientes de que essas propriedades não foram inicializadas.
O quarto método para corrigir esses erros é atribuir um valor a cada uma dessas propriedades:
classe NoInitProperties {a: número=5; b: string=”letra”; }
Aqui, atribuímos o valor numérico de 5 à propriedade a e o valor da string”letter”à propriedade b.
noImplicitThis
A opção do compilador noImplicitThis irá garantir que esta palavra-chave seja acessada corretamente ou então o compilador irá lançar um erro indicando acesso incorreto a ela.
Vamos considerar o seguinte código:
class NoImplicitThisClass {name: string=”Tom”; logToConsole () {deixar callback=function () {console.log (`this.name: $ {this.name}`); } setTimeout (retorno de chamada, 1000); }}
Aqui, temos uma classe chamada noImplicitThisClass que tem uma propriedade de nome inicializada com um valor de string de Tom.
Além disso, a classe define uma função chamada logToConsole que, quando chamada, aciona a função retorno de chamada após dois segundos. Esta classe é usada da seguinte maneira:
let instanceOfClass=new NoImplicitThisClass (); instanceOfClass.logToConsole ();
Aqui, criamos uma variável chamada instanceOfClass para manter uma instância de NoImplicitThisClass e chamar a função logToConsole produzirá o seguinte:
this.name: undefined
Aqui está o que aconteceu: o this propriedade não faz referência à classe NoImplicitThisClass. Isso se deve ao escopo dessa propriedade no JavaScript. Em JavaScript, este escopo nos métodos não está vinculado a nenhuma referência por padrão.
Se a opção do compilador noImplicitThis estiver ativada, o compilador gerará o seguinte erro:
erro TS2683:’this’tem implicitamente o tipo’any’porque não tem uma anotação de tipo
Aqui, o compilador nos notifica que nossa referência a this.name dentro da função de retorno de chamada não está referenciando a propriedade this da classe NoImplicitThisClass.
Resolvendo problemas noImplicitThis
Este erro pode ser resolvido passando esta propriedade para a função de retorno de chamada da seguinte forma:
let callback=function (_this) {console.log (`this.name: $ {_ this.name} `); } setTimeout (retorno de chamada, 2000, este);
Aqui, adicionamos um parâmetro denominado _this à função de retorno de chamada e, em seguida, passamos o valor disso para a chamada setTimeout.
Outra maneira comum de resolver esse erro é usar uma função de seta. Isso é muito comum no React:
let callback=()=> {console.log (`this.name: $ {this.name}`); } setTimeout (callback, 2000)
Aqui, substituímos a palavra-chave da função pela sintaxe da função de seta.
Ambas as soluções terão o seguinte resultado:
this.name: Tom
Eu uso a função de seta com frequência para lidar com esses problemas em meus projetos React e recomendo usar a função de seta, pois é muito mais limpa.
noImplicitReturns
A opção do compilador noImplicitReturns irá garantir que cada função declarada com um valor de retorno deve retornar o valor conforme definido na função.
Vamos considerar o seguinte código:
function fetchUsernameById (id: número): string {if (id===2) retornar”Sam”; } console.log (`fetchUsernameById (4): $ {fetchUsernameById (4)}`)
Aqui, fetchUsernameById tem um id de parâmetro do tipo number e retorna um valor de string. A função verifica se o valor passado como argumento é igual a 2. Se for, retorna o valor da string Sam. No entanto, se o valor do argumento não for igual a 2, nada será retornado.
Esta será a saída da execução deste código:
fetchUsernameById (4): undefined
Aqui, podemos ver que a função fetchUsernameById retorna undefined para qualquer valor do argumento que não seja igual a 2.
Se a opção do compilador noImplicitReturns definida como true, o compilador irá gerar um erro:
erro TS7030: Não todos os caminhos de código retornam um valor.
Resolvendo problemas noImplicitReturns
Este erro pode ser resolvido retornando um valor de string para ids que não são iguais a 2:
function fetchUsernameById (id: number): string {if (id===2) retornar”Sam”; return”Nenhum usuário com tal id”}
Aqui, adicionamos uma instrução de retorno no final da função que retornará a string “Nenhum usuário com tal id” sempre que a função for chamada com um argumento de um valor não igual a 2.
strictNullChecks
A opção do compilador strictNullChecks é usada para encontrar instâncias em nosso código onde o valor de uma variável pode ser nulo ou indefinido no momento do uso.
Vamos considerar o seguinte código:
let a: number; deixe b=a;
O código acima irá gerar o seguinte erro:
erro TS2454: A variável’a’é usada antes de ser atribuída
Este erro nos diz que o valor da variável a é usado quando ainda não foi atribuído um valor.
Tecnicamente, o valor de a pode ser indefinido.
Resolvendo problemas de strictNullChecks
Este erro pode ser resolvido garantindo que seja atribuído um valor à variável a antes de ser usado:
deixe um: número=4; deixe b=a;
Aqui, simplesmente atribuímos o valor 4 à variável chamada a, e isso resolverá o erro.
Outra maneira de corrigir esse erro é usar o tipo de união para informar ao compilador que nós estamos cientes de que a variável pode não estar atribuída no momento do uso, e nós mesmos cuidaremos das consequências:
deixe um: número | Indefinido; deixe b=a;
Conclusão
Neste artigo, demos uma olhada nas várias opções avançadas de compilador disponíveis para configurar nosso compilador TypeScript. Também vimos as mensagens de erro associadas a cada opção do compilador e como resolvê-los.
Verifique a documentação oficial do Typescript para mais opções do compilador .