Como evitar importações com caminhos relativos muito longos no Angular 2?

95

Como posso apresentar algo como 'my-app-name/services'evitar linhas como a importação a seguir?

import {XyService} from '../../../services/validation/xy.service';
Thomas Zuberbühler
fonte

Respostas:

138

TypeScript 2.0+

No TypeScript 2.0, você pode adicionar uma baseUrlpropriedade em tsconfig.json:

{
    "compilerOptions": {
        "baseUrl": "."
        // etc...
    },
    // etc...
}

Então você pode importar tudo como se estivesse no diretório base:

import {XyService} from "services/validation/xy.service";

Além disso, você pode adicionar uma pathspropriedade, que permite combinar um padrão e mapeá-lo. Por exemplo:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "services/*": [
                "services/validation/*"
            ]
        }
        // etc...
    },
    // etc...
}

O que permitiria a você importá-lo de qualquer lugar como:

import {XyService} from "services/xy.service";

A partir daí, você precisará configurar qualquer carregador de módulo que esteja usando para oferecer suporte a esses nomes de importação também. No momento, o compilador TypeScript não parece mapeá-los automaticamente.

Você pode ler mais sobre isso na edição do github . Também existe uma rootDirspropriedade que é útil ao usar vários projetos.

Pre TypeScript 2.0 (ainda aplicável em TS 2.0+)

Descobri que pode ser mais fácil usando "barris" .

  1. Em cada pasta, crie um index.tsarquivo.
  2. Nesses arquivos, reexporte cada arquivo da pasta.

Exemplo

No seu caso, primeiro crie um arquivo chamado my-app-name/services/validation/index.ts. Neste arquivo, tenha o código:

export * from "./xy.service";

Em seguida, crie um arquivo chamado my-app-name/services/index.tse tenha este código:

export * from "./validation";

Agora você pode usar seu serviço da seguinte forma ( indexestá implícito):

import {XyService} from "../../../services";

E depois de ter vários arquivos lá, fica ainda mais fácil:

import {XyService, MyOtherService, MyOtherSerivce2} from "../../../services";

Ter que manter esses arquivos extras dá um pouco mais de trabalho inicial (o trabalho pode ser eliminado usando o mantenedor do barril ), mas descobri que compensa no final com menos trabalho. É muito mais fácil fazer grandes alterações na estrutura de diretório e reduz o número de importações que você precisa fazer.

Cuidado

Ao fazer isso, há algumas coisas que você deve observar e não pode fazer:

  1. Você deve observar as reexportações circulares. Portanto, se os arquivos em duas subpastas referirem-se um ao outro, você precisará usar o caminho completo.
  2. Você não deve voltar para uma pasta da mesma pasta original (por exemplo, estar em um arquivo na pasta de validação e fazer import {XyService} from "../validation";). Eu descobri isso e o primeiro ponto pode levar a erros de importação não sendo definida.
  3. Finalmente, você não pode ter duas exportações em uma subpasta com o mesmo nome. Normalmente, isso não é um problema.
David Sherret
fonte
2
@ ThomasZuberbühler Acho que no TypeScript 1.8 que estará disponível ( veja aqui ).
David Sherret
3
Como faço o download do Typescript 2.0+ com npm?
maximedupre
4
Uma pequena dica - depois de ler a documentação, descobriu-se que o baseUrlé relativo à localização de 'tsconfig.json'. Portanto, em nosso caso (aplicativo angular), o valor tinha que ser "baseUrl": "./app",, onde "app" é a raiz do aplicativo.
Pawel Gorczynski de
10
Somente usuários angular-cli : se você estiver usando angular-cli 2+, eles mudaram para webpack e blackboxed webpack.config.js (dentro de node_modules). "A partir daí, você precisará configurar qualquer carregador de módulo que esteja usando para oferecer suporte a esses nomes de importação também." Como o webpack.config.js está em uma caixa preta, você não pode fazer essa parte. Felizmente, descobri que o problema já foi relatado aqui e resolvido por este PR. TL; DR, a configuração do webpack em caixa preta é inteligente o suficiente para examinar tsconfig.json agora.
Kevin
1
para usuários do angular-cli, você pode gerar um webpack.config com "ng eject". Observe que você precisará remover o ejected: true de .angular-cli.json -> project para poder servir ao projeto.
Drusantia
14

Melhor usar a configuração abaixo em tsconfig.json

{
  "compilerOptions": {
    "...": "reduced for brevity",

    "baseUrl": "src",
    "paths": {
      "@app/*": ["app/*"]
    }
  }
}

Maneira tradicional antes do Angular 6:

`import {XyService} from '../../../services/validation/xy.service';`

deve ser refatorado nestes:

import {XyService} from '@app/services/validation/xy.service

Curto e grosso!

Shivang Gupta
fonte
esta mudança não funciona na produção @shivangGupta
anônimo
1

Acabei de encontrar esta questão. Eu sei que é um caminho de volta agora, mas para qualquer um que encontrar isso, há uma resposta mais simples.

Eu descobri apenas porque algo que eu estava fazendo há muito tempo parou de funcionar e eu queria saber se algo mudou no Angular 7. Não, era apenas meu próprio código.

Independentemente disso, eu só tive que alterar uma linha tsconfig.jsonpara evitar caminhos de importação longos.

{
  "compilerOptions": {
  "...": "simplified for brevity",

   "baseUrl": "src"
  }
}

Exemplo:

// before:
import {XyService} from '../../../services/validation/xy.service';

// after:
import { XyService } from 'app/services/validation/xy.service';

Isso tem funcionado muito para mim desde o surgimento do Angular-CLI.

Chris Curnow
fonte
Obrigado pelo esforço Chris, mas você deveria ter fornecido exemplos de uso em sua resposta!
George43g 01 de