Tslint: no-implicit-dependencies: suporte ao mapeamento de caminho

Criado em 20 out. 2017  ·  18Comentários  ·  Fonte: palantir/tslint

Relatório de erro

  • __TSLint version__: 5.8.0
  • __TypeScript version__: 2.7.0-dev.20171020
  • __ Executando TSLint via__: CLI

Código TypeScript sendo vinculado

src / a.ts

import { x } from "foo";

types / foo.d.ts

export const x = 0;

tsconfig.json

{
    "compilerOptions": {
        "paths": {
            "*": "types/*"
        }
    }
}

com configuração tslint.json :

{
    "rules": {
        "no-implicit-dependencies": true
    }
}

Comportamento real

ERROR: /home/andy/sample/tslint/src/a.ts[1, 19]: Module 'foo' is not listed as dependency in package.json

Comportamento esperado

Sem erro. Acho que se uma importação não for resolvida para algo em node_modules esta regra deve ignorá-la.

Comentários muito úteis

Esta regra não funciona quando usamos alias para nosso próprio código-fonte (não para importar de pacotes npm). É muito útil usar o caminho absoluto em vez do caminho relativo.
Em nosso tsconfig.json, para um aplicativo angular, precisamos apenas adicionar:

"compilerOptions": {
  ...
  "baseUrl": "./src",
  "paths": {
    "~/env": ["environments/environment"],
    "~/*": ["app/*"]
  }
}

Então podemos fazer importações como:

import {FooService} from '~/core';
import {Environment} from '~/env';

Talvez devamos reabrir esse problema para resolver este caso (não há necessidade de node_modules, apenas o arquivo tsconfig.json).
Agradeço esta regra, por isso será lamentável desativá-la.

Todos 18 comentários

Acho que se uma importação não for resolvida para algo em node_modules, essa regra deve ignorá-la.

A regra não tenta resolver os módulos. Isso significaria que você precisa ter todas as dependências instaladas, o que não é realmente possível com peerDependencies e optionalDependencies. Com a implementação atual, você pode criar um clone novo sem instalar nada. Acho que é isso que a maioria das ferramentas de qualidade de código faz.

Pelo que entendi os mapeamentos de caminho, eles só existem em tempo de compilação. Em tempo de execução, você ainda precisa do módulo instalado para node / webpack / qualquer coisa para pegá-lo corretamente.
Isso significa que os mapeamentos de caminho são relevantes apenas se você tiver apenas importações de tipo que são omitidas durante a compilação. Nesse caso, a regra provavelmente não é a escolha certa para você.

Em nosso caso, geralmente não há package.json , então acho que devemos simplesmente desabilitar essa regra. Obrigado!

No meu caso, estou "importando" projetos separados de texto digitado em que estou trabalhando simultaneamente usando mapeamento de caminho:

"compilerOptions": {
    ...
    "paths": {
        "tsbase": ["../tsBaseProject/src"],
        "tslibrary": ["../tsProjectLibrary/src"]
    }
}

para que eu possa usá-los no projeto como se fossem módulos.
Existe uma maneira de colocá-los na lista de permissões?

@marcoqu Os mapeamentos de dependencies ou peerDependencies ao seu package.json

Quando eu compilo a fonte principal que "importa" os projetos secundários, tudo é compilado em um único pacote como se fossem pastas reais no projeto. Não preciso colocá-los na pasta node_modules.
Para ser claro, nas pastas secundárias do projeto, tenho arquivos .ts reais, não apenas as declarações de tipo.

+1 para adicionar uma lista de permissões como em importações de no-submodule

Também temos o caso de usarmos o caso em que definimos um alias de caminho '~' para o diretório base a fim de evitar importações relativas. Este alias é posteriormente resolvido por webpack, fuse-box, etc. Começando com 5.8, tslint cospe muitos erros espúrios por causa disso ...

O que ele disse ^^

Após a atualização, agora tenho centenas desses erros pelos mesmos motivos descritos acima. Uma espécie de regra sem sentido.

Esta regra não funciona quando usamos alias para nosso próprio código-fonte (não para importar de pacotes npm). É muito útil usar o caminho absoluto em vez do caminho relativo.
Em nosso tsconfig.json, para um aplicativo angular, precisamos apenas adicionar:

"compilerOptions": {
  ...
  "baseUrl": "./src",
  "paths": {
    "~/env": ["environments/environment"],
    "~/*": ["app/*"]
  }
}

Então podemos fazer importações como:

import {FooService} from '~/core';
import {Environment} from '~/env';

Talvez devamos reabrir esse problema para resolver este caso (não há necessidade de node_modules, apenas o arquivo tsconfig.json).
Agradeço esta regra, por isso será lamentável desativá-la.

@ andy-ms, por favor, reconsidere os caminhos de suporte (nós os usamos extensivamente com nx espaços de trabalho). Esta é uma regra muito útil, mas por enquanto sou forçado a desativá-la.

Tentei examinar o código-fonte e consertar precisaria ir em algum lugar ao longo dessas linhas . Também verifiquei como o Typescript está lidando com isso e rastreei essa função . Definitivamente, não é uma tarefa fácil duplicar essa lógica. Não tenho certeza se essa função pode ser reutilizada, há um monte de argumentos dos quais não tenho certeza.

Eu gostaria muito de ver isso sendo corrigido também. O mapeamento de caminho é um recurso altamente valorizado. Também tentei usar módulos vinculados como solução alternativa, mas também não há suporte para eles.

Eu descobri uma solução alternativa que resolve um pouco o problema para mim, mas não tenho certeza de que irá resolver para todos, ou que seja de alguma forma sustentável. De qualquer forma, a solução é a seguinte:

Adicione um pacote falso a optionalDependencies com o nome do mapa de caminho de tsconfig.json e instale as dependências usando npm install --no-optional . Isso infelizmente não funciona com yarn --ignore-optional - ele ainda falha ao tentar buscar o pacote.

Portanto, com caminhos em tsconfig.json parecidos com isto:

    "paths": {
        "~/*": ["src/*"],
        "some-path/*": ["whatever/*"]
    }

E opcional em package.json assim:

    "optionalDependencies": {
        "~": "tslint-hack",
        "some-path": "tslint-hack"
    },

Deve ser possível obter dependências de produção e desenvolvimento para instalar usando npm install --no-optional . Isso obviamente assume que você não precisa de nenhuma dependência opcional instalada. Também vale a pena mencionar que não funcionou com @ como o nome do pacote.

Se você escolher usar este hack, provavelmente seria inteligente adicionar um arquivo .npmrc à raiz do projeto, com optional=false configurado, para que você possa voltar a executar npm install sem a bandeira --no-optional .

Outra solução que _deve_ funcionar é realmente criar um pacote com o nome desejado e publicá-lo em um registro privado, usando verdaccio ou similar. Acredito que seja possível configurar registros privados por módulo usando .npmrc ou .yarnrc e, como tal, deve ser melhor em termos de sustentabilidade. Porém, nada disso é testado.

Espero que isso possa ajudar um pouco para aqueles que desejam usar esta regra tslint e manter suas resoluções de módulo em vigor. Mas não é um substituto para uma correção adequada.

Também tendo esse problema, resultando em sonar sinalizando isso incorretamente como um cheiro de código.

Acho que esta é uma solicitação válida, já que tslint tem tudo a ver com texto digitado e caminhos são uma configuração válida (e importante) de texto digitado.

E se eu tiver package.json em um diretório diferente daquele de tslint.json ?

- web
    - package.json
    - ClientApp
        - tslint.json

Estou trabalhando em uma configuração semelhante e estou recebendo erros em quase todos os arquivos devido a esta regra. Alguma solução para isso?

A maneira que descobri para contornar esse problema é usando a seguinte opção de configuração.

"no-implicit-dependencies": [true, ["src", "app", "~"]]

Ele lista os caminhos fornecidos. Obviamente, isso significa duplicação, mas é uma solução rápida, se você estiver procurando por uma.

Para aqueles de nós que usam símbolos @ como prefixos para caminhos personalizados, levantei um PR para corrigir um pequeno bug com a implementação atual # 4192

"no-implicit-dependencies": [true, ["@src", "@app", "~"]]

@ifiokjr Eu estava usando @ como meu alias src, então minhas importações pareciam @/components
Não foi possível definir @ como caminho ignorado, pois tentou importar @/components como um módulo inteiro em vez de resolver @ primeiro.

Mudei meu alias para ~ e usei a linha acima em meu tslint, resolvendo o problema

Esta página foi útil?
0 / 5 - 0 avaliações