Introdução

Os processos de construção no TypeScript podem se tornar bastante complexos quando temos que configurar nosso fluxo de projeto manualmente por meio do arquivo tsconfig.json . Isso ocorre porque essas configurações exigem compreender o compilador TypeScript e o sistema de módulos .

Tendo trabalhado em muitos projetos TypeScript sozinho, consegui identificar dois problemas comuns que surgem ao usar módulos TypeScript e, mais importante, como resolvê-los de forma eficaz.

Pré-requisitos

Para obter o máximo deste artigo, você vai querer se preparar com o seguinte:

  • Uma sólida experiência em JavaScript e TypeScript
  • Uma sólida compreensão do sistema de módulos TypeScript

Problema 1: localização irregular das dependências

Em uma ocasião normal, o diretório node-modules está geralmente localizado no diretório raiz (ou seja, baseUrl) do projeto, conforme mostrado abaixo:

 projectRoot
├── node_modules
├── src
│ ├── file1.ts
│ └── file2.ts
└── tsconfig.json
└── package.json

Às vezes, no entanto, os módulos não estão localizados diretamente no baseUrl . Por exemplo, dê uma olhada no seguinte código JavaScript:

//index.js
importar expresso de"expresso";

Carregadores como webpack usam uma configuração de mapeamento para mapear o nome do módulo (neste caso, express ) para o arquivo index.js em tempo de execução, traduzindo assim o trecho acima para node_modules/express/lib/express em tempo de execução.

Neste ponto, quando usamos o snippet traduzido acima em um projeto TypeScript, devemos configurar o compilador TypeScript para lidar com a importação do módulo usando a propriedade "caminhos":

//tsconfig.json
{ "compilerOptions": { "baseUrl":"./src", "caminhos": { "express": ["node_modules/express/lib/express"] } }
}

No entanto, com a configuração acima, o compilador TypeScript gerará o seguinte erro:
módulo expresso não encontrado

Aqui está o que está acontecendo nos bastidores: o compilador TypeScript procura node_modules no diretório src , embora node_modules esteja localizado fora do diretório src , determinando assim que o módulo não foi encontrado.

Solução 1: localize o diretório correto

O mapeamento em "caminhos" é resolvido em relação a "baseUrl". Portanto, nossa configuração deve ser a seguinte:

//tsconfig.json
{ "compilerOptions": { "baseUrl":"./src",//Deve ser especificado se"caminhos"for. "caminhos": { "express": ["../node_modules/express/lib/express"]//Este mapeamento é relativo a"baseUrl" } }
}

Quando usamos esta configuração, o compilador TypeScript “salta” um diretório do diretório src e localiza o diretório node_modules .

Como alternativa, a configuração abaixo também é válida:

//tsconfig.json
{ "compilerOptions": { "baseUrl":".",//Isso deve ser especificado se"caminhos"for. "caminhos": { "express": ["node_modules/express/lib/express"]//Este mapeamento é relativo a"baseUrl" } }
}

Quando usamos esta configuração, o compilador TypeScript irá procurar o diretório node_modules no diretório raiz do projeto.

Problema 2: vários locais de fallback

Nosso segundo problema comum também está relacionado à localização. Vamos considerar a seguinte configuração de projeto:

 projectRoot
├── ver
│ ├── file1.ts (importa'view/file2'e'nav/file3')
│ └── file2.ts
├── componentes
│ ├── rodapé
│ └── nav
│ └── file3.ts
└── tsconfig.json

Aqui, o módulo view/file2 está localizado no diretório view e nav/file3 no diretório de componentes.

Resolver módulos em vários locais pode ser um pouco desafiador porque, neste ponto do código, o compilador não sabe como resolver esses módulos em locais diferentes. Na seção a seguir, revisaremos como resolver esse problema.

Solução 2: Localize o módulo e resolva as importações

Usando a configuração abaixo, podemos dizer ao compilador para procurar em dois locais (ou seja, ["*","components/*"] ) para qualquer importação de módulo no projeto:

 { "compilerOptions": { "baseUrl":".", "caminhos": { "*": ["*","componentes/*"] } }
}

Neste exemplo, o valor "*" na matriz significa o nome exato do módulo, enquanto o valor "components/*" é o nome do módulo ( “Componentes) com um prefixo anexado.

Agora podemos instruir o compilador a resolver as duas importações da seguinte maneira:

 import'view/file2'

O compilador irá então substituir 'view/file2' pelo primeiro local na matriz ("*") e combiná-lo com o baseUrl que resulta em projectRoot/view/file2.ts . Isso permitirá que o módulo seja encontrado.

Após esta etapa, o compilador irá para a próxima importação:

 import'nav/file3':

Da mesma forma, o compilador substituirá 'nav/file3' pelo primeiro local na matriz ("*")-também conhecido como nav/file3 -e combine-o com o baseUrl que resulta em projectRoot/nav/file3.ts . Desta vez, o arquivo não existe, então o compilador substituirá 'nav/file3' pelo segundo local "components/*" e o combinará com o baseUrl . Isso resultará em projectRoot/components/nav/file3.ts , permitindo que o módulo seja encontrado.

Como o TypeScript resolve módulos por padrão

Sem configurar o compilador TypeScript conforme discutido anteriormente, o TypeScript adotará a estratégia de resolução de tempo de execução Node.js por padrão para localizar os módulos solicitados em tempo de compilação.

Para fazer isso, o compilador TypeScript procurará arquivos.ts,.d.ts,.tsx e arquivos package.json. Se o compilador encontrar um arquivo package.json, ele verificará se esse arquivo contém uma propriedade de tipos que aponta para um arquivo de digitação. Se nenhuma propriedade for encontrada, o compilador tentará procurar os arquivos de índice antes de passar para a próxima pasta.

Aqui está um exemplo. Uma declaração de importação como import {b} from'view/file2' em /projectRoot/view/file1.ts resultaria na tentativa dos seguintes locais para localizar ".view/file2":

  1. O /projectRoot/view/file2.ts existe?
  2. O /projectRoot/view/file2.tsx existe?
  3. O /projectRoot/view/file2.d.ts existe?
  4. Existe /projectRoot/view/file2/package.json (se especifica uma propriedade "types")?
  5. O /projectRoot/view/file2/index.ts existe?
  6. O /projectRoot/view/file2/index.tsx existe?
  7. O /projectRoot/view/file2/index.d.ts existe?

Se o módulo não for encontrado neste ponto, o mesmo processo será repetido, saltando uma etapa da pasta pai mais próxima da seguinte maneira:

  1. O /projectRoot/file2.ts existe?
  2. O /projectRoot/file2.tsx existe?
  3. O /projectRoot/file2.d.ts existe?
  4. Existe /projectRoot/file2/package.json (se especifica uma propriedade "types")?
  5. O /projectRoot/file2/index.ts existe?
  6. O /projectRoot/file2/index.tsx existe?
  7. O /projectRoot/file2/index.d.ts existe?

Conclusão

Às vezes, podemos nos deparar com algumas situações complexas em que diagnosticar porque um módulo não foi resolvido pode ser muito difícil. Em tais situações, habilitar o rastreamento da resolução do módulo do compilador usando tsc--traceResolution pode fornecer mais informações sobre o que aconteceu durante o processo de resolução do módulo, permitindo-nos escolher a solução correta no futuro.

Com os problemas comuns dos módulos TypeScript destacados e as soluções fornecidas neste post, espero que seja um pouco mais fácil configurar o compilador TypeScript para manipular módulos em seus projetos TypeScript.

Esperamos que você tenha achado esta postagem informativa e útil. Você também pode verificar a documentação oficial do TypeScript para se aprofundar na resolução do módulo TypeScript.

A postagem Problemas comuns do módulo TypeScript e como resolvê-los apareceu primeiro no LogRocket Blog .

Source link