Typescript: Declarações de tipo duplicado com link npm

Criado em 15 jan. 2016  ·  147Comentários  ·  Fonte: microsoft/TypeScript

Usando TypeScript 1.7.3.

Suponha que eu tenha os pacotes npm abaixo.
Os arquivos de declaração são gerados pelo compilador TypeScript e referidos a partir de outros pacotes por meio da maneira descrita aqui .

pacote-a

ts src:

export default class ClassA {
  private foo: string;
  bar: number;
}

declaração ts:

declare class ClassA {
  private foo;
  bar: number;
}
export default ClassA;

package-b (depende do package-a):

ts src:

import ClassA from 'package-a';

namespace ClassAFactory {
  export function create(): ClassA {
    return new ClassA();
  }
}
export default ClassAFactory;

declaração ts:

import ClassA from 'package-a';

declare namespace ClassAFactory {
  function create(): ClassA;
}
export default ClassAFactory;

package-c (depende de package-a e package-b):

ts src:

import ClassA from 'package-a';
import ClassAFactory from 'package-b';

let classA: ClassA;
classA = ClassAFactory.create(); // error!!

A última linha causa um erro durante a compilação:

error TS2322: Type 'ClassA' is not assignable to type 'ClassA'.
Types have separate declarations of a private property 'foo'.

Quando removo a linha private foo; da declaração do pacote-a, o TypeScript não emite nenhum erro.
No entanto, essa solução alternativa é um pouco dolorosa.

Eu entendo que expor propriedades privadas para declaração é intencional (https://github.com/Microsoft/TypeScript/issues/1532).
Acho que o TypeScript deve ignorar as propriedades privadas ao compilar a atribuição de variável.
Ou existe alguma solução melhor para isso?

@types Bug Fixed

Comentários muito úteis

Acabei de mesclar uma alteração que tentará detectar pacotes duplicados com base em seu nome e versão, e usar apenas um. Experimente usando typescript@next na próxima publicação.

Todos 147 comentários

Há apenas uma declaração de raiz de ClassA aqui, então este erro não deve ocorrer.

Bem, desculpe, descobri que isso está relacionado a npm link .

Quando eu uso npm link , os pacotes são instalados conforme abaixo, pois ele simplesmente cria links simbólicos.

package-c
|
-- node_modules
    |
    -- package-a
    |   |
    |   -- index.d.ts
    |   |
    |   ...
    |
    -- package-b
        |
        -- index.d.ts
        |
        -- node_modules
        |   |
        |   -- package-a
        |       |
        |       -- index.d.ts
        |       |
        |       ...
        |
        ...

Conforme mostrado, parece que há dois arquivos de declaração diferentes para o pacote-a.
Se eu instalar pacotes normalmente usando npm install , isso não acontecerá porque a declaração de pacote-a não está incluída no pacote-b neste caso.

Espero que haja alguma solução para isso de qualquer maneira, mas pode ser difícil e de baixa prioridade.

Acabei não usando npm link , e isso não importa mais para mim.

É justo, mas outra pessoa pode: piscar:

na verdade, existem dois arquivos no disco com duas declarações de ClassA. então o erro está correto. mas precisamos considerar os módulos de nó quando comparamos esses tipos. esse problema foi relatado antes em https://github.com/Microsoft/TypeScript/issues/4800 , para Enums, alteramos a regra para uma verificação semimonital. possivelmente faça o mesmo para as aulas.

+1 nisso com o TS 1.7.5 com todos os pacotes relevantes vinculados ao NPM. Tentei construir um caso de teste que exibisse o problema, mas não consegui. Não importa o que eu tentei, o TS estava bem com o cenário que vejo falhando com o TS2345 em meu aplicativo e, tanto quanto eu poderia dizer, todas as cópias do arquivo .d.ts problemático eram links simbólicos para o mesmo arquivo, então não deveria tem havido declarações diferentes dentro do tipo. No entanto, seria bom se o erro emitido pelo Typescript fizesse referência aos arquivos que declararam os dois tipos incompatíveis, pois isso pode lançar luz sobre algo que não estou considerando. No momento, ele diz que existem duas definições, mas não faz nada para ajudar o desenvolvedor a identificar o problema.

Como alternativa, você pode usar <any> na expressão conflitante para pular a verificação de tipo. Obviamente, isso pode exigir que você faça outra anotação de tipo onde talvez não tivesse feito antes. Espero que alguém possa isolar esse problema em algum momento.

EDIT: deixei claro que o link NPM está em jogo no meu caso

O TS 1.8 avisado está disponível, atualizado e o problema ainda existe nessa versão.

Obrigado por todo o trabalho de análise e documentação deste problema. Estamos tendo o mesmo problema em algumas de nossas bases de código. Transferimos alguns projetos para usar apropriadamente package.json dependências, mas agora estamos vendo isso ao usar npm link durante o desenvolvimento.

Posso ajudar em alguma coisa a resolver esse problema?

Estou usando o Lerna, que fornece links simbólicos para pacotes, e também estou vendo o problema. Typcript versão 2.0.3.

Infelizmente, o Lerna e seus links simbólicos são um requisito difícil, então usei esta solução desagradável para fazer com que isso compilasse bem e ainda fosse devidamente verificável pelos consumidores:

export class MyClass {
  constructor(foo: Foo) {
    (this as any)._foo = foo;
  }

  get foo() {
    return (this as any)._foo as Foo;
  }
}

A classe é muito pequena, então não foi tão árdua, e não espero que mude realmente, e é por isso que considero esta uma solução alternativa aceitável.

Para sua informação, também acabei aqui como resultado de usar npm link e receber este erro. Alguém encontrou uma solução alternativa para isso?

@xogeny você pode explicar como o link npm está causando esse problema para você?

@mhegazy Bem, comecei a receber esses erros como o acima (exceto que estava usando Observable de rxjs , ou seja, "O tipo 'Observável' não pode ser atribuído ao tipo 'Observável'). claro, parecia estranho porque os dois que eu estava me referindo Observable exatamente da mesma versão de rxjs em ambos os módulos. Mas onde os tipos "se encontraram", eu obtive um erro. Eu procurei e eventualmente encontrei este problema onde @kimamula apontou que se você usar npm link , você obterá este erro. Eu, como outros, contornei isso (no meu caso, criei uma interface duplicada apenas da funcionalidade que necessário em um módulo, em vez de referências rxjs ).

Isso responde à sua pergunta? Pergunto porque não acho que meu caso seja diferente dos outros aqui, então não tenho certeza se isso ajuda você.

Fizemos um trabalho no TS2.0 especificamente para habilitar cenários npm link (consulte https://github.com/Microsoft/TypeScript/pull/8486 e # 8346). Você tem uma amostra em que eu possa ver onde o link npm ainda não está funcionando para você?

Hã. Estou executando 2.0.3 (verifiquei). Vou tentar criar uma caixa reproduzível.

A propósito, você deve acompanhar esses tópicos, pois eles sugerem que isso ainda é um problema no TS 2.0:

https://github.com/ReactiveX/rxjs/issues/1858
https://github.com/ReactiveX/rxjs/issues/1744

O problema que estou vendo em meu repositório Lerna está um tanto envolvido, então fiz uma versão simplificada dele em https://github.com/seansfkelley/typescript-lerna-webpack-sadness. Pode até ser falha do webpack / ts-loader, então eu também arquivei https://github.com/TypeStrong/ts-loader/issues/324 lá.

Estou usando o typescript 2.0.3 e estou vendo este erro com Observable conforme descrito acima, por exemplo,

Type 'Observable<Location[]>' is not assignable to type 'Observable<Location[]>'. Property 
            'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

Eu estou acertando isso em um pacote Lerna monorepo também. Parece que a maioria, mas não todas as partes do sistema de tipos, estão usando o caminho real para identificar arquivos de forma exclusiva. Se você viajar pelo ramo que está usando o caminho do link simbólico em vez do caminho real, você acabará com tipos idênticos, mas diferentes.

Este é um problema bastante brutal que afetará apenas bases de código mais complexas e parece impossível de contornar sem tomar medidas drásticas, então espero poder convencer todos vocês a dar a ele a atenção que merece. 😄

É mais perceptível nos casos em que você tem um aplicativo que depende da Dependência A, a Dependência A depende da Dependência B e vends objetos que contêm tipos da Dependência B. O aplicativo e a Dependência A npm link Dependência B e espera ser capaz de importar tipos dele e fazer com que descrevam a mesma coisa.

Isso resulta em mensagens de erro profundas e estou prestes a eliminar todas as propriedades private e protected em minhas bibliotecas porque já perdi muito tempo com isso :

TSError: ⨯ Unable to compile TypeScript
tests/helpers/test-application.ts (71,11): Argument of type '{ initializers: Initializer[]; rootPath: string; }' is not assignable to parameter of type 'ConstructorOptions'.
  Types of property 'initializers' are incompatible.
    Type 'Initializer[]' is not assignable to type 'Initializer[]'.
      Type 'Application.Initializer' is not assignable to type 'Application.Initializer'.
        Types of property 'initialize' are incompatible.
          Type '(app: Application) => void' is not assignable to type '(app: Application) => void'.
            Types of parameters 'app' and 'app' are incompatible.
              Type 'Application' is not assignable to type 'Application'.
                Types of property 'container' are incompatible.
                  Type 'Container' is not assignable to type 'Container'.
                    Types of property 'resolver' are incompatible.
                      Type 'Resolver' is not assignable to type 'Resolver'.
                        Types of property 'ui' are incompatible.
                          Type 'UI' is not assignable to type 'UI'.
                            Property 'logLevel' is protected but type 'UI' is not a class derived from 'UI'. (2345)

Realmente agradeço a todos vocês olhando para isso; obrigado!

@tomdale você está usando o Webpack, tsc ou outra ferramenta de construção? Meu problema parece acontecer apenas quando compilado via Webpack (veja o repositório vinculado do meu comentário anterior ).

@seansfkelley Isso se parece com https://github.com/TypeStrong/ts-node.

Isso mesmo, ele está usando ts-node (para o aplicativo raiz). As dependências, entretanto, são pacotes compilados com tsc .

Acabei de encontrar esse problema, que é um grande problema para nós, porque tentamos dividir nosso back-end em várias bibliotecas pequenas. Durante o desenvolvimento, geralmente precisamos vincular o npm aos nossos repositórios. O problema específico que encontrei e que me levou a descobrir isso é o uso de rxjs Observables e interfaces:


// in repo A
export class HttpAdapter {
    request(url: string, options?: HttpRequestOptionsArgs): Observable<HttpResponse> {
        return Observable.of({});
    }
}

// in repo B
export class HttpRequestAdapter implements HttpAdapter {
    request(url: string, options?: HttpRequestOptionsArgs): Observable<HttpResponse> {
        return Observable.of({});
    }
}

Isso funciona se eu não npm link , mas quando o faço, recebo:

Error:(10, 14) TS2420:Class 'HttpRequestAdapter' incorrectly implements interface 'HttpAdapter'.
  Types of property 'request' are incompatible.
    Type '(url: string, options?: HttpRequestOptionsArgs) => Observable<HttpResponse>' is not assignable to type '(url: string, options?: HttpRequestOptionsArgs) => Observable<HttpResponse>'.
      Type 'Observable<HttpResponse>' is not assignable to type 'Observable<HttpResponse>'.
        Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

A única sugestão que posso fazer é evitar private . Não publico mais nenhum pacote com private por causa deste problema e apenas uso prefixos _ estilo JavaScript. Encontro-o com https://github.com/Microsoft/TypeScript/issues/7755, que é uma discussão semelhante sobre por que private entra em um sistema de tipo nominal em vez de estrutural e, portanto, o bani no meu próprios projetos porque é muito fácil acabar com diferenças de versão (por exemplo, NPM 2 ou usando npm link ).

@blakeembrey quando você diz evitar privado, sugere que eu posso alterar algo no meu código? Estou assumindo que a definição de tipo Observable é o problema, não?

@jeffpressedpley Sim, desculpe, você não é o culpado. É Observable . Infelizmente, o conselho para evitar private é muito limitado e não era inteiramente aplicável a você 😄 Talvez você possa fazer uma questão, estou assumindo, rxjs sobre o uso de private em suas interfaces públicas?

Edit: Eu comentei principalmente porque havia seguido o problema anteriormente e evitado juntar-me às minhas próprias experiências, mas percebi que também poderia escrever meus pensamentos novamente, em vez de eles serem semelhantes a https://github.com/Microsoft/TypeScript/issues/ 6496 # issuecomment -255232592 (onde @tomdale sugere a eliminação de private e protected , fiz o mesmo há algum tempo).

Tive a impressão de @mhegazy que ele achava que não havia problema com npm link . Mas ainda parece estar nos atormentando e a outros. Então, não tenho certeza de onde está esse problema? É um problema reconhecido com o TS 2.0+ ou estou apenas perdendo uma solução alternativa em algum lugar?!?

Estou tendo o mesmo problema e não parece ser causado por npm link . Ainda consigo se instalar usando npm install file.tar.gz . Aqui está o erro:

app/app.component.ts(46,5): error TS2322: Type 'Observable<boolean | Account>' is not assignable to type 'Observable<boolean | Account>'.
  Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

Esta é a aparência do meu app.component.ts :

export class AppComponent implements OnInit {
  private user$: Observable<Account | boolean>;
  private loggedIn$: Observable<boolean>;
  private login: boolean;
  private register: boolean;

  constructor(public stormpath: Stormpath) {}

  ngOnInit() {
    this.login = true;
    this.register = false;
    this.user$ = this.stormpath.user$;
    this.loggedIn$ = this.user$.map(user => !!user);
  }

Ele está reclamando da linha this.user$ . Stormpath tem user$ definido como o seguinte:

@Injectable()
export class Stormpath {

  user$: Observable<Account | boolean>;

@xogeny Estranho, meu entendimento era que a definição de identidade estava ligada à localização do arquivo, o que significa que eles sempre vão causar problemas usando npm link (porque a dependência npm link ed teria suas próprias dependências instaladas) . Talvez a identidade da definição tenha sido alterada - usar hashes de arquivo pode ser uma boa solução alternativa no TypeScript. Infelizmente, há apenas uma dúzia de maneiras diferentes de acabar com módulos duplicados em JavaScript ( npm install do GitHub, npm install , clones manuais, conflitos de versão podem até resultar na mesma versão em locais diferentes por causa de como funciona o algoritmo de resolução do módulo do nó, etc).

@blakeembrey Talvez. Mas então o que foi isso ?

Observe, não estou reclamando. Estou apenas tentando descobrir se há alguma esperança de que isso seja resolvido ou não. É um espinho sério em nosso lado por todos os motivos mencionados por @jeffadvantpley .

@xogeny eu sei, estou tentando também, adoraria ver isso resolvido corretamente 😄 Eu li os problemas vinculados, mas todos eles são projetados para resolver o caminho real de um link simbólico, o que implica se você tem dois arquivos (reais) eles ainda entrarão em conflito porque resolverão para locais diferentes. Que é o que acontece quando você npm link de um projeto para outro, já que ambos teriam suas próprias dependências que podem diferir com símbolos reexportados do pacote npm link ed.

Edit: posso confirmar, todos os problemas são por causa de dois arquivos. npm link o acionaria porque é simples ter uma dependência em um repo que você acabou de vincular que é a mesma dependência do projeto ao qual você vinculou. Uma reprodução simples seria fazer npm install da mesma dependência em dois níveis diferentes de um aplicativo e observar o erro deles.

image

Para qualquer pessoa que segue este tópico ... Eu tentei a solução alternativa descrita aqui e parece funcionar (até agora).

Eu reproduzi este erro.

mkdir a; cd a
npm install rxjs
echo 'import * as rx from "rxjs"; export const myObservable: rx.Observable<number>;' > index.d.ts
echo '{ "name": "a" }' > package.json

cd ..; mkdir b; cd b
npm install rxjs
npm link ../a
echo 'import * as rx from "rxjs"; import * as a from "a"; const x: rx.Observable<number> = a.myObservable;' > index.ts
tsc index.ts --target es6 --moduleResolution node

Como há duas instalações de rxjs , obtemos:

index.ts(1,59): error TS2322: Type 'Observable<number>' is not assignable to type 'Observable<number>'.
  Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

Eu tenho uma solução alternativa que funciona muito bem para linha de comando, mas o Visual Studio ainda fica confuso: https://github.com/Microsoft/TypeScript/issues/11107#issuecomment -254003380

minha nova solução alternativa para o Windows + Visual Studio 2015 é copiar minhas pastas xlib Library src e dist e node_modules\xlib\src e node_modules\xlib\dist do projeto consumidor.

aqui está a parte significativa do meu script de arquivo em lote robocopy, se alguém quiser:

:rerunloop
    <strong i="14">@echo</strong> watching for changes to project files..............  (Ctrl-C to cancel)

    <strong i="15">@rem</strong> xlib --> blib and slib
    <strong i="16">@robocopy</strong> .\xlib\src .\blib\node_modules\xlib\src *.*  /MIR /NJH /NJS /NDL /XD .git
    <strong i="17">@if</strong> NOT "%errorlevel%" == "0" (
        <strong i="18">@rem</strong> copy occured, so copy both

        <strong i="19">@robocopy</strong> .\xlib\dist .\blib\node_modules\xlib\dist *.*  /MIR /NJH /NJS /NDL /XD .git   
        <strong i="20">@robocopy</strong> .\xlib\src .\slib\node_modules\xlib\src *.*  /MIR /NJH /NJS /NDL /XD .git     
        <strong i="21">@robocopy</strong> .\xlib\dist .\slib\node_modules\xlib\dist *.*  /MIR /NJH /NJS /NDL /XD .git

        <strong i="22">@rem</strong>  set the src dirs readonly
        <strong i="23">@attrib</strong> +R .\blib\node_modules\xlib\src\*  /S /D
        <strong i="24">@attrib</strong> +R .\slib\node_modules\xlib\src\*  /S /D
    )
    <strong i="25">@timeout</strong> /t 1 /nobreak > NUL
<strong i="26">@goto</strong> rerunloop

Desculpe por incomodar novamente com este problema, mas é um obstáculo sério em nosso projeto não poder fazer npm link enquanto estamos fazendo alterações. Eu adoraria ajudar com um RP se um dos colaboradores atuais do TypeScript pudesse me dar algumas orientações sobre onde começar a procurar na base de código.

Eu também estou lutando com este. Adotamos o TS a partir de um pequeno aplicativo, agora o dividimos em submódulos e os vinculamos e ... BOOM. TS não compilará mais. Isso ainda é um problema em todos os TS dist-tags? No momento, estou experimentando isso em @rc (2.1.1).

@heruan e @jefftelyy podem dar uma chance a typescript@next , corrigimos alguns problemas relacionados. e se você ainda estiver vendo o problema, forneça mais informações sobre a configuração do projeto.

@mhegazy , estou em Version 2.2.0-dev.20161129 e ainda estou tendo o problema. O problema específico é que tenho um projeto (vamos chamá-lo de Projeto A) que contém uma "interface" (usando uma classe, mas para que eu possa usar a classe como um token para Angular 2 DI) da seguinte maneira:

export class ServerAdapter {
    start(opts: ServerOptions): Observable<any> {
        return null;
    }
}

Em seguida, em um projeto completamente separado (vamos chamá-lo de Projeto B) que tem uma classe que implementa a interface do primeiro projeto assim:

export class RestifyServerAdapter implements ServerAdapter {
    start(opts: ServerOptions): Observable<any> {
        let server = restify.createServer();
        this.addPreprocessors(server);
        this.addRequestHandler(server, opts);
        return this.startServer(server, opts);
    }

   // more stuff here that is not relevant to this issue
}

Quando eu faço uma compilação de texto digitado normal para ProjectB, funciona bem. Mas se eu npm link ProjectA do diretório raiz do ProjetoB e, em seguida, executo tsc novamente, recebo:

Types of property 'start' are incompatible.
    Type '(opts: ServerOptions) => Observable<any>' is not assignable to type '(opts: ServerOptions) => Observable<any>'. Two different types with this name exist, but they are unrelated.
      Type 'Observable<any>' is not assignable to type 'Observable<any>'. Two different types with this name exist, but they are unrelated.
        Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

Não consegui replicar em um projeto simulado, acho que não estou entendendo a causa do problema, portanto, não consigo replicá-lo. @jeffpressionpley, você pode publicar um projeto de simulação replicando o problema? Eu acho que um projeto Lerna deve ser bom e facilmente testável.

@heruan , vou tentar configurar isso.

Um, FYI, no entanto. Acho que posso ter encontrado uma solução alternativa. O problema será resolvido se eu npm link rxjs no ProjetoA e no ProjetoB. Isso faz sentido porque, nesse caso, tanto o ProjetoA quanto o ProjetoB estão usando exatamente os mesmos arquivos rxjs. Sem isso, eles estão tecnicamente usando arquivos diferentes (embora sejam da mesma versão):

Se você apenas npm link ProjectA do ProjetoB, então:

  • ProjetoB está apontando para node_modules / rxjs
  • ProjectA existe como um link simbólico em node_modules / ProjectA e o rxjs que ele faz referência está em node_modules / ProjectA / node_modules / rxjs

Mas se você npm link rxjs em ambos, então ambas as referências rxjs serão vinculadas simbolicamente ao mesmo local npm global.

De qualquer forma, isso obviamente ainda não é o ideal, mas pelo menos algo que pode nos mover para frente.

Além disso ... não tenho certeza se isso é relevante ou importante (verei assim que configurar o projeto de teste), mas minhas duas bibliotecas (ou seja, ProjetoA e ProjetoB) são, na verdade, repositórios npm privados.

Obrigado @jefflike pela dica, mas como estou usando o Lerna todos os módulos já estão vinculados entre si para que leiam o mesmo arquivo, mas acho que o compilador TS está levando em consideração o caminho do link e não o real. Posso estar errado, já que não posso reproduzir em um projeto simulado, e estou realmente ficando louco ...

Alguém aqui pode resolver isso de uma maneira elegante?

Além disso, observe que este não é apenas um problema com npm link , você terá esse problema também em compilações de produção, quando suas dependências compartilhadas apontarem para uma versão diferente.

ie. ProjetoA precisa de [email protected] e ProjetoB usa [email protected]

Quando você instala o ProjectA como uma dependência no ProjectB, você também terá tipos duplicados, já que haverá por exemplo duas declarações Observable , uma em node_modules/rxjs e uma em node_modules/project_a/node_modules/rxjs

Você pode contornar isso permitindo que a versão rxjs no ProjetoA seja algo como ~4.9.0 , de modo que npm install não precise baixar sua própria versão e, em vez disso, use a versão ProjectB. Mas lembre-se de que esse não é apenas um problema de fluxo de trabalho de desenvolvimento.

Postando aqui de acordo com a sugestão de @andy-ms. Tentei de novo ontem com o mais recente 2.0.xe ainda tinha.

Estou recebendo isso com as tipificações para Angular 1: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/10082#issuecomment -253023107

Corri para isso novamente hoje, especificamente o problema com links simbólicos. Minha configuração é mais ou menos assim:

node_modules/
folder
  another_folder
    node_modules/ (symlinked to ../../node_modules)
    app/ (angular1 app in typescript)
    tsconfig.json
    (other build files)

Se eu apenas tiver @types/angular , tsc funcionará bem. Se eu tiver todo o pacote ( @types/angular-{animate,cookies,mocks,resource,route,sanitize} ), começo a receber muitos erros de tipo:

$ npm run tsc

> [email protected] tsc D:\work\angular.io\public\docs\_examples\upgrade-phonecat-1-typescript\ts
> tsc

../../node_modules/@types/angular/index.d.ts(17,21): error TS2300: Duplicate identifier 'angular'.
../../node_modules/@types/angular/index.d.ts(18,21): error TS2300: Duplicate identifier 'ng'.
app/app.animations.ts(5,3): error TS2339: Property 'animation' does not exist on type 'IModule'.
app/app.config.ts(6,45): error TS2305: Module 'angular' has no exported member 'route'.
app/core/checkmark/checkmark.filter.spec.ts(5,22): error TS2339: Property 'mock' does not exist on type 'IAngularStatic'.
app/core/phone/phone.service.spec.ts(18,22): error TS2339: Property 'mock' does not exist on type 'IAngularStatic'.
app/core/phone/phone.service.spec.ts(23,18): error TS2339: Property 'expectGET' does not exist on type 'IHttpBackendService'.
app/core/phone/phone.service.spec.ts(30,18): error TS2339: Property 'verifyNoOutstandingExpectation' does not exist on type 'IHttpBackendService'.
app/core/phone/phone.service.spec.ts(31,18): error TS2339: Property 'verifyNoOutstandingRequest' does not exist on type 'IHttpBackendService'.
app/core/phone/phone.service.spec.ts(39,18): error TS2339: Property 'flush' does not exist on type 'IHttpBackendService'.
app/core/phone/phone.service.ts(5,33): error TS2305: Module 'angular' has no exported member 'resource'.
app/phone-detail/phone-detail.component.spec.ts(5,22): error TS2339: Property 'mock' does not exist on type 'IAngularStatic'.
app/phone-detail/phone-detail.component.spec.ts(18,46): error TS2305: Module 'angular' has no exported member 'route'.
app/phone-detail/phone-detail.component.spec.ts(20,20): error TS2339: Property 'expectGET' does not exist on type 'IHttpBackendService'.
app/phone-detail/phone-detail.component.spec.ts(32,20): error TS2339: Property 'flush' does not exist on type 'IHttpBackendService'.
app/phone-detail/phone-detail.component.ts(7,37): error TS2305: Module 'angular' has no exported member 'route'.
app/phone-list/phone-list.component.spec.ts(6,22): error TS2339: Property 'mock' does not exist on type 'IAngularStatic'.
app/phone-list/phone-list.component.spec.ts(15,20): error TS2339: Property 'expectGET' does not exist on type 'IHttpBackendService'.
app/phone-list/phone-list.component.spec.ts(26,20): error TS2339: Property 'flush' does not exist on type 'IHttpBackendService'.
node_modules/@types/angular-resource/index.d.ts(192,40): error TS2305: Module 'angular' has no exported member 'resource'.
node_modules/@types/angular/index.d.ts(17,21): error TS2300: Duplicate identifier 'angular'.
node_modules/@types/angular/index.d.ts(18,21): error TS2300: Duplicate identifier 'ng'.

Corrigi-o adicionando a base ../../node_modules/@types como typeRoots ao meu tsconfig.json :

    "typeRoots": [
      "../../node_modules/@types/"
    ]

Tentei adicionar o node_modules/@types , mas não funcionou.

@heruan, um hack que comecei a fazer é implementar meu próprio script npm para vincular / desvincular em vez de usar a funcionalidade lerna. Então, você poderia fazer algo como lerna run link e então em todos os seus arquivos package.json você tem um script npm chamado link que faz todos os links npm incluindo (no meu caso) npm link rxjs . Parece funcionar bem, definitivamente não é o ideal.

@jeffpressedpley você pode compartilhar sua solução aqui?

@yvoronen Não consigo compartilhar todo o meu código, mas minha solução está descrita acima. Em um alto nível, a chave que encontrei é ter certeza de vincular npm não apenas todos os projetos locais em que você está trabalhando, mas também vincular npm as bibliotecas externas que podem estar causando o problema (no meu caso, rxjs é o problema por causa do vars privados no objeto Observable). Então, eu uso o lerna para gerenciar todos os meus projetos locais e, em seguida, executo lerna run link . Nas cenas, isso chama npm run link dentro de cada uma das pastas raiz do meu projeto. Portanto, você precisa ter o script link definido em seu package.json assim:

  "scripts": {
    "link": "npm link my-local-project1 && npm link my-local-project2 && npm link rxjs || true",
    "unlink": "npm unlink my-local-project1 && npm unlink my-local-project2 && npm unlink rxjs && npm i || true"
  }

Esperançosamente, isso faz sentido, mas entre em contato se tiver alguma dúvida.

Eu queria fornecer uma atualização. De uma conversa improvisada que tive com @mhegazy , aqui está o que estamos pensando.

  • Uma solução que estamos considerando é o conceito de diferenciar pacotes com base em sua versão, bem como em seu nome de resolução. Não tenho detalhes completos sobre o que estaria envolvido nisso.
  • Outra é expandir totalmente o caminho para obter a identidade "verdadeira" de um link simbólico. Acredito que isso seja mais simples, mas mais limitado quando se trata de lidar com o mesmo pacote em versões diferentes, mas ajuda a resolver um número razoável de casos.

Tem certeza de que seu comentário pertence a este problema? Soa completamente
diferente.

Na quinta-feira, 12 de janeiro de 2017, 03h14, Nikos [email protected] escreveu:

Observe, não estou usando tipos ou link npm AFAIK.

[imagem: imagem]
https://cloud.githubusercontent.com/assets/216566/21887548/451d059c-d8b8-11e6-86d1-50afae4e5c2f.png

-
Você está recebendo isso porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment-272137732 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAUAmcMXodOvU7coymMqGzTofD4pMagpks5rRgsogaJpZM4HFcWl
.

@dobesv é, na verdade, toda a razão pela qual você vê o problema em primeiro lugar. O TypeScript reconhece a declaração da classe como duas declarações separadas porque não conseguiu distinguir o caminho vinculado por símbolo do caminho verdadeiro. A solução é

  1. Expanda o link simbólico.
  2. Verifique se o pacote que o contém é o mesmo.

@DanielRosenwasser Desculpe, meu comentário foi uma resposta ao comentário de outra pessoa "Em Qui, 12 de janeiro de 2017, 03:14 Nikos @ . * > Escreveu" ... quem é e o que eles disseram Eu não me lembro mais, acredito que eles estavam perguntando sobre algum problema neste tópico de comentários, que não tinha nada a ver com o link npm.

Mas, enquanto estou aqui, devo mencionar que há algo engraçado no modo como o nome do arquivo desempenha um papel nos tipos. Hoje eu tive um problema com o RxJS em que ele reclamou que tal e tal método não foi definido no Observable. O motivo era que a biblioteca HTTP tinha sua própria cópia privada do rxjs que era diferente de todas as outras. Na verdade, encontrei quatro cópias diferentes de rxjs em minha árvore node_modules.

Esta parece ser uma abordagem problemática que continuará a ser problemática e confusa.

Se todo esse conceito de nome de arquivo, de alguma forma, desempenhar um papel na identidade de um tipo fosse embora, acho que esse problema de link npm também desapareceria.

Ainda estou um pouco confuso sobre como isso funcionaria ... Sou novo no TypeScript. Mas esse é o tipo de impressão que estou tendo, é que essa coisa de "nome de arquivo é importante" me causou alguma confusão em conjunto com as bibliotecas que estou usando (ionic2 e angular2 e rxjs).

Bem, o problema é que o nome do arquivo ainda é a identidade de um módulo em Javascript, então ele não pode ir embora completamente. Alguém pode expandir sobre quais são os problemas com o uso do caminho canônico (resolução do link simbólico) com relação a várias versões de pacote? Se houver várias versões de pacote em uma árvore, eles terão vários caminhos canônicos absolutos, certo?

EDIT: Percebi isso depois de postar, e este comentário resume bem:
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -257016094

exclude e compilerOptions.typeRoots são completamente ignorados pelo tsc. Eu tentei todas as combinações para ignorar os caminhos com links simbólicos, mas simplesmente não
está vendo o módulo como um caminho completamente diferente, como se estivesse resolvendo o link simbólico e não entendendo os padrões excluídos.

por exemplo, tenho G:\www\cim-service-locator npm vinculado a npm link cim-service-locator . no caminho do meu projeto em G:\www\cim-backend , os erros estão aparecendo assim:

crop

Eu tentei todas as combinações possíveis de excludes / includes / typesRoot, mas não consegui fazer o tsc ignorá-los. usando 2.2-dev.20170131

Encontramos esse problema usando "npm link" (por meio de um problema SPFx relatado por @waldekmastykarz) e também sem "npm link" (consulte o bug # 11436).

Acabei percebendo que a rigidez do compilador TypeScript se deve a incompatibilidades que podem ocorrer de forma realista devido ao design maluco da pasta node_modules . Considere este exemplo:

A
+---B<strong i="8">@1</strong>
+---C
|   +---B<strong i="9">@2</strong>   <--- first copy of ClassB extends ClassE version 3.4
|   \[email protected]
+---D
|   \---B<strong i="10">@2</strong>   <--- second copy of ClassB extends ClassE version 3.5
\[email protected]

Neste exemplo, B @ 2 tem de ser instalado em sub-pastas para evitar um conflito com a dependência de A em B @ 1 . Agora, suponha que ClassB se estenda de ClassE, e temos algo assim:

B / package.json

{
  "name": "B",
  "version": "2.0.0",
  "dependencies": {
    "E": "^3.0.0",
    ...
}

Se o package.json de C pede [email protected] , então as duas cópias da ClassB podem terminar com diferentes implementações de classe base, o que significa que elas realmente são incompatíveis. O código pode falhar no tempo de execução se você tentar usá-los de forma intercambiável.

Neste exemplo, TS2345 evitaria esse erro, o que é bom. No entanto, NÃO é essencial: se o compilador tratasse as duas cópias da ClassB como equivalentes, seu sistema de tipos ainda seria internamente consistente e teria um comportamento determinístico.

Isso é importante porque para nós o TS2345 produz principalmente alarmes falsos. Esses alarmes falsos forçam as pessoas a escrever "como qualquer um" onde quer que compartilhem tipos entre os pacotes NPM, o que causa outros erros. Portanto, o rigor está criando mais problemas do que resolve.

Eu gostaria de propor a seguinte correção:

Se TODAS essas condições forem verdadeiras, NÃO relate TS2345 para classes com membros privados:

  1. As assinaturas públicas são compatíveis de acordo com a usual digitação TypeScript
  2. As classes são definidas em pastas de pacotes NPM com o mesmo nome e versão (de acordo com package.json)
  3. As classes têm o mesmo caminho relativo para seus módulos (por exemplo, "./lib/blah/Bdts")

Se algum desses critérios não for atendido, não há problema em relatar o TS2345.

@iclanton @ nickpape-msft

@seansfkelley O erro do Webpack é rastreado por TypeStrong / ts-loader # 468

Oi pessoal,
Alguém encontrou uma solução ??
Tenho o mesmo problema quando vinculo um projeto a outro com RxJS.
Obrigado ;)

Olá, uma solução temporária é envolver os Observables retornados por uma dependência com Observable#from .

Nenhuma solução ainda. ?

Parece haver dois problemas aqui.

Os usuários do ts-loader obtendo erros errôneos para definições duplicadas parecem ser causados ​​por entrada inválida na API do compilador. Uma correção para isso está disponível em TypeStrong / ts-loader # 468.

O outro problema é se você tem o mesmo pacote (mesmo pacote npm + versão) instalado duas vezes localmente no sistema de arquivos (não usando npm link ) em duas pastas aninhadas, com Enums ou classes com membros privados, comparando o os tipos desses dois pacotes seriam incompatíveis.
Esse problema é um pouco mais complexo e exigirá trabalho adicional para o compilador "desduplicar" os pacotes antes de processá-los.

Se nenhuma dessas duas categorias se aplicar a você, registre um novo problema e nos forneça informações suficientes para reproduzir o problema localmente, e ficaremos felizes em investigar mais a fundo.

Uma solução alternativa conhecida é usar uma solução multiprojeto que eliminará as pastas duplicadas, ou seja, garantindo que ambas as subpastas node_modules terminem com link simbólico para o mesmo destino.

Rush (que usamos) e Lerna são exemplos.

@smcatala Você pode explicar sua solução. Eu preciso consertar isso urgente. Obrigado.

@ leovo2708
módulo 'foo':

import { Observable } from 'rxjs'
export function foo() {
  return Observable.of('foo')
}

código do cliente em outro módulo, que depende do módulo 'foo':

import { Observable } from 'rxjs'
import { foo } from 'foo'

Observable.of(foo()) // wrap the returned Observable
.forEach(res => console.log(res))

@ leovo2708 a solução simples é não usar npm link .

usando ts 2.1, fui capaz de usar o link npm com uma única biblioteca (vamos chamá-lo de xlib , que é meu exemplo real), mas você precisará certificar-se de que os módulos que sua biblioteca ( xlib ) as cargas não são duplicadas na pasta node_modules do projeto de consumo.

Eu faço isso pelo seguinte fluxo de trabalho

  1. excluir node_modules
  2. npm link xlib que cria o sym_link para xlib no meu projeto de consumo node_modules
  3. npm install que instala o restante das dependências do meu projeto de consumo

Eu realmente não tenho acompanhado esta conversa ou verificado se este problema foi alterado / modificado desde 2.2, mas apenas gostaria de compartilhar minha solução alternativa para ts 2.1

Caso seja útil, juntei uma reprodução mínima das múltiplas definições de caso enums aqui: https://github.com/rictic/repro-npm-link-typescript-issue

@mhegazy Vemos o problema acima ao usar o link npm, embora eu não ache que isso afete o resto de sua análise.

Muito obrigado, espero que seja corrigido em breve. No entanto, usei uma nova solução, duplique todos os arquivos usando Observable. Não é bom, mas apenas uma solução temporária.

tsconfig.json expõe um mapeamento de caminho, adiciona dependências duplicadas em paths , então ele será carregado a partir do node_modules correto em vez de um vinculado.

{
  "compilerOptions": {
    "baseUrl": ".", // This must be specified if "paths" is.
    "paths": {
      "@angular/common": ["../node_modules/@angular/common"],
      "@angular/compiler": ["../node_modules/@angular/compiler"],
      "@angular/core": ["../node_modules/@angular/core"],
      "@angular/forms": ["../node_modules/@angular/forms"],
      "@angular/platform-browser": ["../node_modules/@angular/platform-browser"],
      "@angular/platform-browser-dynamic": ["../node_modules/@angular/platform-browser-dynamic"],
      "@angular/router": ["../node_modules/@angular/router"],
      "@angular/http": ["../node_modules/@angular/http"],
      "rxjs/Observable": ["../node_modules/rxjs/Observable"]
    }
  }
}

Não tenho certeza se já foi mencionado aqui, mas essa solução funcionou para mim: https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001

É basicamente igual à solução de

Essa é uma ótima ideia @charpeni. Usei essa configuração de caminhos para solucionar vários outros problemas semelhantes, mas também parece ideal para este. Na verdade, eu me pergunto se a configuração paths correta no projeto de consumo (em vez de em cada projeto consumido) pode distrair o compilador TypeScript da resolução de nó seguinte. Se funcionar, seria um hack O (1) em vez de um hack O (n). Essencialmente, esse esquema executaria a resolução do nó estaticamente e, em seguida, colocaria os resultados no tsconfig.

Estou experimentando essas coisas semi-publicamente se alguém quiser assistir (ou ajudar ...). Provavelmente tentarei a ideia acima a seguir.

https://github.com/OasisDigital/many-to-many-angular

Para facilitar o uso, você também pode definir os caminhos como este:

{
    "compilerOptions": {
        "baseUrl": ".", // This must be specified if "paths" is.
        "paths": {
            "@angular/*": ["../node_modules/@angular/*"],
            "rxjs/*": ["../node_modules/rxjs/*"]
        }
    }
}

O link npm é uma parte crucial do fluxo de trabalho ao trabalhar com vários pacotes, ao contrário de uma arquitetura mono-repo. O TS deve ser capaz de ver que os dois pacotes são idênticos e não apresentam erros

@charpeni Não consegui fazer a solução alternativa funcionar. Só para ficar claro, a qual tsconfig.json isso deve ser adicionado? O pacote raiz ou o pacote vinculado?

Também estou enfrentando esse problema. De repente, começou a acontecer na segunda-feira, e não tenho certeza do porquê. Isso está realmente atrapalhando o desenvolvimento, especialmente quando se trata de desenvolver pacotes para nossos projetos. Tentei várias soluções alternativas para corrigir isso. A execução de mklink /j no Windows ainda causa esse problema, portanto, não é um problema de link npm. Se alguém tiver uma solução alternativa ou uma solução, isso seria de grande ajuda.

Minha solução alternativa é vincular o npm a cada pacote "duplicado" no pacote raiz e na dependência, porque eles se referem aos mesmos arquivos novamente.

A propósito, este problema não tem nada a ver com @types

Acabamos usando o padrão glob.

@felixfbecker Para a implementação, está disponível aqui: https://github.com/sherweb/ng2-materialize/blob/master/demo-app/tsconfig.json#L19 -L22

Eu tenho um problema semelhante, exceto que está totalmente relacionado a @ types / node.

libA depende de @ node / types
libB depende de libA e @ node / types
libC depende de libA, libB e @ node / types

libA constrói bem.
libB npm vinculado ao arquivo de construção libA.
libC npm ligado a libA e libB falha na verificação de tipos com erros como

libC/node_modules/@types/node/index.d.ts(102,6): Duplicate identifier 'BufferEncoding'.
libC/node_modules/libB/node_modules/@types/node/index.d.ts(102,6): Duplicate identifier 'BufferEncoding'.
libC/node_modules/libB/node_modules/libA/node_modules/@types/node/index.d.ts(102,6): Duplicate identifier 'BufferEncoding'.

Eu tentei mexer com "tipos" e "typeRoots" sem sorte.

@charpeni Parece que seu projeto também depende de @ types / node. Você tem alguma ideia da solução para o meu problema ou de uma solução alternativa?

@nicksnyder que pode ser porque são versões diferentes, e @types/node é uma declaração global, o que significa que você não pode definir os mesmos nomes duas vezes. Esta é a razão pela qual é melhor que os pacotes _não_ dependam de tipificações ambientais, estas devem ser fornecidas pelo usuário:
https://github.com/Microsoft/types-publisher/issues/107

@nicksnyder Eu tive um problema semelhante e fui capaz de contorná-lo ligando por npm todos os três projetos a uma única instalação de @ types / node. Uma vez que as definições são definidas no mesmo arquivo, elas não são mais duplicatas

@felixfbecker Eu verifiquei que todos os projetos dependem da mesma versão do nó.

FWIW libA é https://github.com/Microsoft/vscode-languageserver-node/tree/master/jsonrpc , libB é https://github.com/Microsoft/vscode-languageserver-node/tree/master/client e libC é minha própria extensão do VS Code.

@uncleramsay como exatamente você npm link @types/node ?

???
cd libA; npm link @types/node
cd libB; npm link @types/node
cd libC; npm link @types/node

Eu gostaria de fazer a solução de vinculação, mas também cortei isso excluindo a dependência @ types / node em libA e libB e adicionei um refs.d.ts que contém referências locais para a cópia do nó de libC.

/// <reference path='../../../path/to/libC/node_modules/@types/node/index.d.ts'/>

Descobri que era capaz de resolver os problemas que estava tendo a partir da descrição no comentário em https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -225303098

nós apenas adicionamos suporte para resolução de links simbólicos para módulos ...

Em locais separados na base de código quando estávamos usando dois estilos de referência diferentes:

/// <reference path="../node_modules/@types/library" />
/// <reference types="library" />

Esses dois são incompatíveis no caso em que node_modules são vinculados simbolicamente, já que a resolução do módulo (com types= ) é expandida para o realpath, mas path= não é. Isso resulta em dois arquivos diferentes referenciados ao compilar com tsc --listFiles , o link simbólico e o caminho real.

A solução que escolhemos foi usar um ou outro, mas nunca os dois. Também ajudou a especificar typeRoots: [] no tsconfig para evitar que o compilador carregue automaticamente os tipos de node_modules/@types no caso de usar o estilo reference path= .

Acredito que a preferência daqui para frente (pelo menos para nós) é preferir o estilo types= .

Porém, o ideal é expandir para o caminho real em reference path= e verificar se há caminhos correspondentes duplicados para evitar tais problemas.

Espero que ajude alguém.

@nicksnyder, você deve ser capaz de fazer algo assim:

cd libA/node_modules/@types/node; npm link
cd libB; npm link @types/node
cd libC; npm link @types/node

Dessa forma, B e C estão apontando para os mesmos arquivos que A está.

@uncleramsay esteja ciente de que são todas as mesmas versões, o que podem não ter sido antes

As dependências dos pares não podem ser uma solução para isso?
http://codetunnel.io/you-can-finally-npm-link-packages-that-contain-peer-dependencies/

As dependências de mesmo nível foram inventadas para uma situação em que um plug-in deseja dizer o que acompanha. Eles meio que funcionam bem para esse caso. Mas eles causam muitos problemas se as pessoas começarem a converter todas as suas dependências em dependências de mesmo nível, na esperança de evitar a duplicação do "npm install".

Passamos meses banindo-os de nossos repositórios git internos. Quando usadas como acho que você está sugerindo, as dependências de pares permitem que você resolva um problema de controle de versão lado a lado trocando-o por vários novos problemas:

  • toda a árvore é invertida, ou seja, cada pacote agora se torna responsável por assumir uma dependência rígida de pacotes que costumavam ser dependências indiretas, em muitos casos sem nenhuma ideia para que serve

  • se uma dependência de par for removida, essas dependências rígidas provavelmente nunca serão removidas

  • autores de pacotes são tentados a usar amplas faixas para seus padrões de versão de pares, alegando trabalhar com versões contra as quais eles nunca testaram; compilações quebradas de repente se tornam o problema do consumidor

Bem dito.

soluções alternativas

Aqui estão três opções para soluções alternativas que usei:

opção 1: use vscode, não visual studio

O compilador tsc é muito mais tolerante do que o VS2017, provavelmente porque o VS2017 rastreia o código (incluindo node_modules com link simbólico) para fornecer uma boa inteligência e, portanto, fica confuso. No entanto, tenho grandes projetos complexos de módulos multi-npm, então use o VS2017 ... então leia as opções 2 e 3 se você tiver necessidades semelhantes ...

opção 2: emitir d.ts

se você usar outDir e rootDir (em seu tsconfig.json ), seu módulo lib vinculado deve emitir d.ts declarações e essas declarações devem estar no módulo lib package.json types propriedade.

aqui está um exemplo de como o tsconfig.json do seu módulo lib deve se parecer

{
  "compileOnSave": true,
  "compilerOptions": {
    "module": "commonjs",
    "sourceMap": true,
     "declaration": true,
    "jsx": "react",
    "newLine": "LF",
    "pretty": true,
    "stripInternal": true,
    "diagnostics": true,
    "target": "es5",
    "moduleResolution": "node",
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "rootDir": "./src",
   //workaround for npm linking projects and associated dupe identifier bugs: https://github.com/Microsoft/TypeScript/issues/9566#issuecomment-287633339
    "baseUrl": "./",
    "paths": {
      "*": [
        "node_modules/@types/*",
        "*",
        "custom-dts/*"
      ]
    }
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}

e o package.json seu módulo lib deve incluir algo como o seguinte:

  "main": "./dist/_index.js",
  "types": "./dist/_index.d.ts",

Esta opção funciona bem, o principal problema é que no Visual Studio ao depurar ou "ir para a definição" ou "mostrar todas as referências", ele mostrará a você d.ts não os arquivos-fonte reais, o que anula o principal benefício do Visual Studio (navegação em grandes projetos)

se você quiser ver um exemplo real disso à solta, olhe para o módulo npm xlib v8.5.x

opção 3: emitir .js inline com a fonte (minha escolha favorita)

Você pode usar seus .ts arquivos diretamente para digitar em módulos lib ligados por link simbólico! mas apenas se você não usar o arquivo outDir`` and rootDir in your tsconfig.json```. Isso permitirá que a referência ao VS2017 funcione corretamente. Aqui estão as configurações de que você precisa:

{
  "compileOnSave": true,
  "compilerOptions": {
    "module": "commonjs",
    "sourceMap": true,
     //"declaration": true,
    "jsx": "react",
    "newLine": "LF",
    "pretty": true,
    "stripInternal": true,
    "diagnostics": true,
    "target": "es5",
    "moduleResolution": "node",
    "forceConsistentCasingInFileNames": true,
    //"outDir": "./dist",
    //"rootDir": "./src",
   //workaround for npm linking projects and associated dupe identifier bugs: https://github.com/Microsoft/TypeScript/issues/9566#issuecomment-287633339
    "baseUrl": "./",
    "paths": {
      "*": [
        "node_modules/@types/*",
        "*",
        "custom-dts/*"
      ]
    }
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}

e package.json seu módulo lib deve ser alterado para:

  "main": "./src/_index.js",
  "types": "./src/_index.ts",

advertências (coisas que não funcionarão com a opção 3)

As soluções alternativas acima funcionam apenas se cada módulo lib NÃO emitir informações de tipo redundante. Por exemplo, eu costumava ter minha biblioteca xlib expondo as definições de tipo @types/async . Mas então eu tinha outra biblioteca que também fazia referência independente a @types/async . Usar os arquivos .ts diretamente para digitação faz com que tsc importe async de dois módulos lib, o que faz com que vire com várias formas de duplicate identifier questões. para resolver isso, você precisa não importar o mesmo @types de vários módulos lib, ou usar a opção 2 .d.ts workaround

resumo

Espero que isso possa economizar as horas que levei ... No geral, isso é extremamente doloroso e espero que a equipe de datilografia consiga corrigir os módulos com link simbólico. Mas pelo menos meio que funciona agora (antes da 2.x, era basicamente impossível)

A solução alternativa postada por @mhegazy em https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001 (uma variação da solução alternativa 2 @jasonswearingen) resolveu isso para nós ao usar módulos vinculados em um projeto lerna!

Eu apenas pensei em compartilhar minha experiência ... tentando criar / extrair uma biblioteca de um projeto existente para que a biblioteca possa ser compartilhada entre outros projetos.

Windows 10 Enterprise
VS 2015 Atualização 3
Ferramentas para VS2015 2.2.2
Código VS 1.12.2
Texto datilografado 2.2.2
NPM: 3.10.9
Nó: 6.9.2

Temos um projeto VS 2015 ASP.MVC com um front-end Angular 4.1.x do qual começamos a extrair alguns componentes para fazer uma biblioteca comum para que possam ser usados ​​em outros projetos.

O projeto da biblioteca é construído usando o VS Code e usa rollup para construir as versões es2015, es5 e umd na pasta dist junto com os arquivos d.ts apropriados.

O resultado final é mais ou menos assim:

-- dist
    |
    -- mylib
        |-- <strong i="16">@myscope</strong>
            |-- mylib.es5.js
            |-- mylib.js
        |-- bundles
            |-- mylib.umd.js
        |-- src
            |-- [all the d.ts folders/files]
        |-- index.d.ts
        |-- package.json
        |-- public_api.d.ts

Eu vinculei o npm a pasta dist / mylib à pasta do meu projeto VS 2015 / Angular 4.1.x.

Quando tento compilar o projeto no VS 2015, recebo o mesmo tipo de mensagens conforme descrito em algumas das situações acima para Assinatura, Observável, etc.

Ex: Build: Argument of type 'Subscription' is not assignable to parameter of type 'Subscription'.

Se eu excluir temporariamente o diretório node_modules do projeto de biblioteca, recebo novos erros reclamando de não ser capaz de encontrar módulos:

ex: Build: Cannot find module 'rxjs/Observable'.

O que me leva à conclusão de que, quando o compilador de script compila o aplicativo, ele de fato procura na pasta node_modules do pacote de minha biblioteca vinculada as definições de módulo para minha biblioteca e não na pasta de aplicativos node_modules.

Não está claro para mim quais soluções propostas acima fornecerão uma solução alternativa para esse problema. Alguém poderia me ajudar?

Obrigado!

@mikehutter Em seu projeto que usa sua biblioteca (não na própria biblioteca), faça algo assim em seu tsconfig:

    "paths": {
      "rxjs/*": ["../node_modules/rxjs/*"]
    },

Você pode precisar de alguns pequenos ajustes dependendo de onde seu tsconfig e o código-fonte resultam.

(Como outros neste tópico, adoraria ver alguns aprimoramentos do TypeScript que tornassem isso desnecessário.)

@mikehutter , adicionamos recentemente algumas orientações no Angular CLI para trabalhar com bibliotecas vinculadas e parece que, no seu caso, você está perdendo a configuração de caminhos do TypeScript para RxJs em seu aplicativo de consumidor. Consulte https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/linked-library.md para obter mais informações.

@kylecordes está no ponto 👍

Obrigado @kylecordes e @filipesilva! Isso era tudo que eu precisava ...

Oi!

@mhegazy , você acredita que isso vai chegar a 2,4 ou provavelmente será adiado novamente?
É realmente doloroso contornar isso, forçando cada projeto a sempre definir mapeamentos de caminho para coisas com as quais eles realmente não deveriam se preocupar.

Realmente espero que desta vez isso chegue ao lançamento!

melhor,

Acho que isso ainda não foi mencionado, mas a maneira simplificada de contornar esse problema é:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "*": ["node_modules/*", "*"]
        }
    }
}

A entrada paths acima basicamente diz: para qualquer módulo, primeiro procure-o na pasta node_modules na raiz do projeto, depois volte para a regra normal (recursiva percorra os diretórios de onde a importação ocorreu).

(Por favor, corrija-me se eu estiver errado, ainda sou relativamente novo no TS).

A entrada em paths parece ser relativa a baseUrl . Portanto, se você definir baseUrl para estar em uma subpasta, será necessário alterar a definição de seus caminhos de acordo. Por exemplo:

{
    "compilerOptions": {
        "baseUrl": "./src",
        "paths": {
            "*": ["../node_modules/*", "*"]
        }
    }
}

@fiznool fyi faz parte das minhas opções de soluções alternativas 2 e 3 (na postagem acima). Eu vi que apenas definir a propriedade paths não é suficiente se você tiver projetos com links simbólicos que usam as mesmas tipificações.

@jasonswearingen sua postagem é muito mais abrangente do que a minha ... obrigado por esclarecer isso. Voltarei a consultá-lo se tiver mais problemas. 😄

Estamos vendo isso em projetos do Google também. Conforme descrito aqui:
https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -306969543

As soluções alternativas descritas acima usando baseUrl e caminhos não parecem funcionar, tsc ainda pega as definições duplicadas e nenhuma combinação de caminhos / baseUrl / include / exclude / etc. foi capaz de convencê-lo do contrário.

Estou curioso para saber como isso funciona normalmente, se você tem um projeto que depende de X e também depende de Y que depende transitivamente de X, como o tsc evita carregar as definições de tipo duas vezes?

@esprehn Eu recomendo fortemente que você leia minha postagem de solução alternativa aqui: https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -302886203

em relação a esse link, ambas as minhas soluções (2 e 3) exigem mais do que apenas definir o baseUrl e os caminhos, então, se isso é tudo que você está fazendo, leia novamente. a maneira "fácil" é a solução 2, mas minha preferência é a solução 3, pois permite "navegar para a definição" adequada via estúdio visual. o problema com a solução 3 é que você só precisa ter definições externas .d.ts carregadas uma vez na cadeia de dependências.

espero que ajude.

+1 Estou usando lerna e uma subdependência com tipificações incluídas é sinalizada como "duplicada" quando incluída por meio de dependências vinculadas.

Posso compartilhar o código, se necessário.

Com o WebPack como no Angular-CLI, faça com que o Angular-CLI package.json referencie o pacote RXJS e remova o pacote `RXJS 'de qualquer outro package.json do projeto que você não precisa por causa do WebPack .

Esta situação pode acontecer não apenas com links simbólicos, mas com npm-shrinkwrap.json em uma dependência com @types/node em dependencies . O embrulho faz com que npm instale duas versões idênticas de @types/node no pacote pai e no pacote embalado. Consulte https://github.com/KingHenne/custom-tslint-formatters/issues/5

Também ocorreu isso ao usar um projeto de reação que tem @types/react instalado e vinculá-lo a um aplicativo que também usa @types/react

Eu estava tendo o mesmo problema enquanto trabalhava com pacotes de yarn link .
Rx.js estava lançando um erro: Type 'Observable<Location[]>' is not assignable to type 'Observable<Location[]>'. Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'

Felizmente, resolvi isso usando a mesma versão Rxj.s nos pacotes pai e vinculados.
Portanto, no meu caso, duas versões diferentes de Rx.js causaram o problema.

Este é um grande bloqueador ao trabalhar com monorepos. Realmente espero que isso não seja mais atrasado e encontre seu caminho para 2.5.

Editar: 😮

image

Interessante. O monorepo é o único cenário em que minha equipe NÃO encontra esse problema, porque os links simbólicos apontam tudo de volta para uma pasta de pacote comum.

Minha equipe tem encontrado esse problema com bastante frequência ao vincular nossas próprias bibliotecas internas durante o desenvolvimento.

Recentemente, encontramos uma ferramenta chamada yalc que atenua isso muito bem e, na verdade,

Este problema parece ser continuamente repelido. Como isso é realmente prejudicial para o fluxo de trabalho de tantas pessoas, poderíamos ter algum tipo de solução temporária, como um 'comentário sobre desativação', conforme sugerido em # 9448?

import { baz$ } from './qux';
function foo (bar$: Observable<any>) {}

foo(baz$);
> Duplicate identifier

// Makes foo's `bar$` type equal to that of `baz$`
foo(/*typescript:identicalIdentifier*/ baz$);

O "comentário de desabilitação" não é muito melhor do que simplesmente fazer conversões de tipos em todos os lugares, o que é muito doloroso em um projeto grande. Acima, propus a seguinte mudança de compilador:

Se TODAS essas condições forem verdadeiras, NÃO relate TS2345 para classes com membros privados:

  1. As assinaturas públicas são compatíveis de acordo com a usual digitação TypeScript
  2. As classes são definidas em pastas de pacotes NPM com o mesmo nome e versão (de acordo com package.json)
  3. As classes têm o mesmo caminho relativo para seus módulos (por exemplo, "./lib/blah/Bdts")

Se algum desses critérios não for atendido, não há problema em relatar o TS2345.

Uma correção simplificada também seria melhor do que a situação atual, por exemplo, considere apenas o nº 1, talvez apenas se as pessoas aceitarem via tsconfig. Deve ser muito barato de implementar.

Essa abordagem tem a vantagem de meramente desabilitar alarmes falsos, mas mantendo a semântica existente. Considerando que os hacks de remapeamento de node_modules mudam a resolução do módulo NPM de uma maneira potencialmente incorreta (por exemplo, causando o mau funcionamento do código no exemplo hipotético que dei ).

Para ser honesto, nem tenho certeza se isso deve ser "corrigido" no Typescript, pois também há um problema com o JavaScript simples: o operador instanceof retornará false se a classe do objeto for diferente da classe fornecida.

Portanto, prefiro uma alternativa melhor para o link npm que talvez se conecte ao require () primeiro.

Esse é um bom insight. Você já olhou para o pnpm ? É um pequeno passo à frente do design atual do node_modules, mas muito eficaz se eu o entendi corretamente.

Não se trata apenas de npm link que pode ser substituído ou não usado, mas de ter várias versões do mesmo pacote @types/xxx instaladas ao mesmo tempo, muitas vezes extraídas de dependências que fornecem declarações TypeScript que dependem em declarações padrão, como eu e outras pessoas relatamos. O número de tais pacotes aumentará com mais adoção do TypeScript na comunidade Node.

@Yogu Acho que isso confunde identidade e igualdade. Embora as importações do mesmo pacote / versão de dois locais possam representar duas instâncias diferentes de um tipo, eles ainda são iguais em tipo.

O seguinte código (válido) vem à mente:

type a = { c: string };
type b = { c: string };

function foo (bar: a) {}

const baz: b = { c: 'd' };
foo(baz);

O mesmo se aplica às bibliotecas que importamos.

Os tipos importados das diferentes versões das bibliotecas (e os pacotes @types ) podem ser iguais e diferentes (se a biblioteca for atualizada, a definição do tipo também deve ser atualizada para refletir as mudanças).

Acabei de mesclar uma alteração que tentará detectar pacotes duplicados com base em seu nome e versão, e usar apenas um. Experimente usando typescript@next na próxima publicação.

Viva, muito obrigado por consertar isso! :-)

@pgonzal Obrigado pelo ponteiro para pnpm, isso definitivamente parece interessante!

@sompylasar O @types/node é um caso um pouco especial, mas para @types/react , aqui está minha sugestão: Coloque todas as dependências necessárias para a API de um módulo em peerDependencies , não em dependencies . Isso deixa claro que as versões das dependências devem corresponder (ou pelo menos ser compatíveis) entre os módulos pai e filho. Se pai e filho usam react, mas não trocam objetos do tipo react, este problema aqui não vai surgir.

@harangue Se uma classe é declarada duas vezes em dois arquivos diferentes, com o mesmo nome e a mesma estrutura, ainda existem duas classes distintas que não são consideradas iguais pelo JavaScript. Como mencionei, o operador instanceof ainda distinguirá instâncias das duas classes.

Veja este violino para uma demonstração.

Esse é o motivo pelo qual eu preferiria resolver isso no nível do NPM (para não termos várias declarações em primeiro lugar, se isso não fosse intencional) do que no TypeScript.

@Yogu : +1: então, se @types/node é um caso especial, ou seja, você não pode executar um programa usando duas versões de nó diferentes ao mesmo tempo, será uma versão, e muito provavelmente aquela especificada no pacote de nível superior, talvez o TypeScript deva tratá-lo como um caso especial, por exemplo, sempre usar o @types/node para cada dependência?

@ andy-ms Obrigado por isso!

Por favor, experimente usando typescript @ next quando for publicado.

Presumo que ainda não tenha acontecido. Eu tentei com alguns projetos, mas sem sorte até agora. Seria ótimo ver uma atualização neste tópico assim que next estiver disponível. @ andy-ms

Parece que as compilações diárias pararam novamente. O último foi: 2.5.0-dev.20170808 .

cc / @DanielRosenwasser

Não tenho certeza se isso está relacionado, mas ao tentar 2.5.1, parece que vejo apenas um aspecto de um módulo, mesmo quando ele estende d.ts para outro lugar.

se eu tenho @types para algo, digamos @types/mongodb e tenho uma declaração personalizada que estende esse módulo, ou seja, adicionando promisificação aos métodos, então agora tenho @types/mongodb que tem o módulo mongodb e eu tenho um arquivo d.ts em meu projeto chamado algo como mongo-promisification.d.ts que contém um módulo mongodb .

Então, com o cenário acima, eu tenho um arquivo que tem import {somethingFromTypes} from "mongodb" ele reclama que os dados do módulo de tipos não podem ser encontrados, embora estejam lá e sejam válidos, mas se eu fiz import {somethingFromMyExtendingDts} from "mongodb" isso funciona bem.

Ao compilar, acabo de ser informado de que o módulo não exporta essas coisas, quando o faz, então é o comportamento desejado e eu só preciso reexportar em meu d.ts personalizado ou deve levar em ambos os tipos e a extensão d.ts Eu tenho?

Estou executando a versão de teste mais recente (Windows 10 de 64 bits) e isso não parece ter sido corrigido para mim.

Reprodução

Estrutura

a/
  index.ts
  package.json
b/
  index.ts
  package.json

Corre

cd a
npm link
cd ../b
npm link a

a / index.ts

import { Observable } from 'rxjs/Observable';

export class Foo {
  public bar: Observable<any>;
}

b / index.ts

import { Foo } from '@rxjs-test/a';
import { Observable } from 'rxjs/Observable';

const baz = new Foo();

function qux (quux: Observable<any>) {}

// TypeError
qux(baz.bar);

Corre

b>tsc -v
Version 2.6.0-dev.20170826

b>tsc index.ts
index.ts(11,5): error TS2345: Argument of type 'Observable<any>' is not assignable to parameter of type 'Observable<any>'.
  Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

@grofit Eu acho que o problema na sua situação é que você tem duas declarações de um módulo, onde o que você precisa é um módulo e um aumento.
Você deve ser capaz de fazer mongo-promisification.d.ts assim:

import * as mongodb from "mongodb"; // import the real mongo

// now augment it
declare module "mongodb" {
    // new stuff...
}

Sem o import , você está em um contexto ambiente e está escrevendo uma nova declaração, não um aumento.

(Ref. Manual )

Posso confirmar que agora está funcionando para mim com [email protected] . Muito obrigado a @ andy-ms - esta é uma virada de jogo!

Eu tive o mesmo problema, quando estava importando Observableatravés da biblioteca Typescript para o projeto angular-cli e as funções estavam usando o trecho de código

`` `função getitems (): Observável
http.get (). map (resposta: Resposta) => {
Retornaresponse.json ();
}


and when I removed the Observable<T> from function getitems() to not return anything the error disappear.
```function getitems()
http.get().map(response : Response) =>{
return <T> response.json();
}

@ Basel78 Eu precisaria de um exemplo completo para poder reproduzir seu erro. Além disso, certifique-se de usar typescript@next - angular-cli pode ter uma versão mais antiga que não tem o recurso de desduplicação.

Tentei [email protected], mas ainda recebo muitos erros TS2300: Identificador duplicado.
Infelizmente não posso compartilhar todo o projeto. Mas aqui estão alguns detalhes:
tsconfig do pacote npm-link-ed:

    "compilerOptions": {
        "module": "amd",
        "target": "es3",
        "sourceMap": true,
        "noEmitHelpers": true,
        "experimentalDecorators": true,
        "baseUrl": ".", // This must be specified if "paths" is.
        "paths": {
            "lib/*": [ "src/lib/*" ],
            "modules/*": [ "src/modules/*" ],
            "vendor/*": [ "src/vendor/*" ]
        },
        "typeRoots" : ["src/typings"]
    },
    "include": [
        "src/**/*.ts",
        "src/**/.*.ts", // TS ignores file names starting with dot by default
        "tests/**/*.ts",
        "tests/**/.*.ts"
    ]

o tsconfig do projeto principal ( @croc/webclient é o pacote vinculado):

    "extends": "./node_modules/@croc/webclient/tsconfig",
    "include": [
        "src/**/*.ts",
        "src/**/.*.ts",
        "node_modules/@croc/webclient/src/**/*.ts",
        "node_modules/@croc/webclient/src/**/.*.ts"
    ],
    "compilerOptions": {
      "baseUrl": ".",
      "typeRoots" : ["node_modules/@croc/webclient/src/typings"],
      "paths": {
        // map runtime paths to compile-time paths
        "lib/*": [ "node_modules/@croc/webclient/src/lib/*" ],
        "modules/*": [ "node_modules/@croc/webclient/src/modules/*" ],
        "vendor/*": [ "node_modules/@croc/webclient/src/vendor/*" ]
      }
    }

@ evil-shrike você pode reduzir seu projeto a um exemplo simples que demonstra o problema?

@mhegazy aqui é
https://github.com/evil-shrike/typescript-npmlink-issue
na raiz do objeto:

cd lib
npm link
cd ../main
npm link tstest-lib

depois em main :

npm run tsc

Olá @ evil-shrike, Limitei o problema a:
lib / tsconfig.json

{
    "compilerOptions": {
        "typeRoots" : ["src/typings"]
    }
}

main / tsconfig.json

{
    "extends": "./node_modules/tstest-lib/tsconfig",
    "include": [
        "node_modules/tstest-lib/src/**/*.ts"
    ]
}

Então, acabamos incluindo ambos (de tsc --listFiles ):

/main/node_modules/tstest-lib/src/typings/jquery/index.d.ts
/lib/src/typings/jquery/index.d.ts

Como node_modules vem de include e não da resolução do módulo, não acho que chamemos realpath nele, então termina como dois arquivos incluídos diferentes.
É melhor não incluir seus node_modules qualquer maneira e, em vez disso, compilá-los separadamente e importá-los da maneira que você faria com qualquer outro pacote externo.

@ andy-ms
Não é fácil de fazer. A biblioteca referenciada no meu caso tem muitos ambientes d.ts que, por exemplo, estendem as interfaces globais. Como JQueryStatic:

interface JQueryStatic {
    cleanData (elems);
}

ou declare prefixos para carregados (requirejs):

declare module "i18n!*" {
    //const m: { [key: string]: string };
    const m;
    export = m;
}

Então, em algum lugar do código-fonte da lib, ele os usa:

const oldCleanData = $.cleanData;
$.cleanData = function (elems: JQuery) {
..
    oldCleanData(elems);
};

Quando tal módulo (da lib) for importado em algum lugar principal, ele falhará na compilação.

No código-fonte de sua biblioteca, você deve usar as diretivas /// <reference types="" /> (ou /// <reference path="" /> ) para garantir que as digitações necessárias estejam presentes sempre que sua biblioteca for importada. Dessa forma, não terá que estar em "incluir"; quando importado, os tipos referenciados serão automaticamente adicionados ao projeto.

@ andy-ms obrigado, refatorei meu lib e agora um projeto onde o npm-link-ed está sendo compilado sem problemas.

Não tenho certeza se essas são reproduções muito grandes, mas estou obtendo a mesma coisa com uma instalação barebones do CLI com angular @ next e typescript @ next para fazer com Observable<T> !== Observable<T> :

https://github.com/intellix/angular-cli-red
https://github.com/intellix/angular-cli-blue

A Blue importa e usa um componente e serviço da Red

@intellix Você poderia obter um exemplo de erros usando apenas a linha de comando tsc ? É difícil dizer qual versão do texto datilografado ng está usando.

@ Andy-ms Ainda estou tendo esse problema. Isso ocorre quando tento usar o link npm entre quaisquer vscode extensões que estou construindo. Todos eles importam vscode que causa erros de identificador duplicado.
TS Version 2.7.0-dev.20171118

Para mim, funcionou mapear, por exemplo, "rxjs / *" para uma pasta rxjs específica dentro de node_modules na seção de caminhos do arquivo tsconfig.
Agora tudo funciona bem com o link npm.

Também vi isso acontecer ao passar de link simbólico para não vinculado de um link de atualização de versão para um pacote.

Veja esta pergunta do SO também: https://stackoverflow.com/questions/38168581/observablet-is-not-a-class-derived-from-observablet

@dakaraphi @JoshuaKGoldberg Você poderia fornecer instruções para reproduzir esses cenários?

Com o novo comportamento, não devemos incluir um pacote se já vimos outro pacote com o mesmo valor de "versão" em seu package.json . Se você tiver várias instalações com versões diferentes, obterá duas cópias diferentes do módulo. Isso pode explicar porque uma atualização de versão interromperia isso, se afetasse apenas uma das duas instalações.

@ andy-ms O exemplo que tenho são os seguintes repositórios:

  1. https://github.com/dakaraphi/vscode-extension-fold
  2. https://github.com/dakaraphi/vscode-extension-common

Eu uso a instalação do npm local para fazer referência a vscode-extension-common de vscode-extension-fold

Se você verificar esses repositórios, eles funcionam atualmente porque tenho uma solução alternativa de mapeamento de caminho em package.json de vscode-extension-fold . No entanto, se bem entendi, não precisarei dessa solução alternativa.

@dakaraphi Obrigado! Parece que o erro se deve ao fato de vscode.d.ts ter sido escrito como uma declaração de ambiente global em vez de um módulo externo. Criei Microsoft / vscode-extension-vscode # 90.

Isso ainda não funciona para mim quando estou tentando vincular 2 pacotes, cada um tendo uma dependência de rxjs . Estou usando [email protected] e [email protected] . Ambos os pacotes estão usando exatamente a mesma versão. Alguém tem uma solução alternativa para isso?

@SamVerschueren Você poderia fornecer instruções específicas para reproduzir o erro? Também teste com typescript@next .

@ andy-ms vou ver o que posso fazer!

@ andy-ms Aqui está um pequeno repositório de reprodução https://github.com/SamVerschueren/ts-link-6496. Usei [email protected] para reproduzir isso.

  1. Instale as dependências de mod-a e mod-b
  2. Compile mod-b com yarn build
  3. Compilar mod-a com yarn build

A etapa 3 falhará com o seguinte erro

src/index.ts(7,15): error TS2345: Argument of type 'UnaryFunction<Observable<string>, Observable<string>>' is not assignable to parameter of type 'UnaryFunction<Observable<string>, Observable<string>>'.
  Types of parameters 'source' and 'source' are incompatible.
    Type 'Observable<string>' is not assignable to type 'Observable<string>'. Two different types with this name exist, but they are unrelated.
      Property 'buffer' is missing in type 'Observable<string>'.
src/index.ts(7,47): error TS7006: Parameter 'result' implicitly has an 'any' type.

Ainda encontrando esse problema com [email protected]. Também tentei typescript @ next e tive o mesmo problema.

A raiz do problema parece ser que os pacotes vinculados ainda fazem referência às definições de tipo em seus próprios node_modules vez de usar as tipificações de node_modules aos quais estão vinculados, quando possível. Isso combinado com o fato de que:

  1. globais não podem ser redefinidos

    • isso faz com que o compilador reclame quando o global é definido tanto no node_modules do projeto pai quanto no node_modules no pacote vinculado

  2. classes que são idênticas não podem ser atribuídas umas às outras

    • isso faz com que o compilador reclame ao tentar atribuir uma variável cujo tipo é uma classe do projeto pai node_modules a um valor retornado pelo pacote vinculado cujo tipo é definido em seu próprio node_modules

Consegui contornar esse problema usando a variável de configuração paths . Para módulos cujas definições vêm de @types/* , conforme sugerido aqui , você pode simplesmente usar:

"paths": {
  "*": ["node_modules/@types/*", "*"]
}

No caso em que você se depara com esse problema com um pacote que vem com definições de tipo que definem classes ou globais, você deve adicioná-los manualmente. Por exemplo, rxjs :

"paths": {
  "rxjs": ["node_modules/rxjs"],
  "rxjs/*": ["node_modules/rxjs/*"]
}

Também tenho problemas com links simbólicos quando adiciono um pacote local, usando TS 2.8.3:

},
"devDependencies": {
    "@types/MyLib": "file:../MyLib/bin/npm/@types"
},

Desde a v3, o npm está aparentemente instalando-os com links simbólicos em vez de copiar os arquivos.

No entanto, quando tento compilar, o compilador vê o arquivo de definição vinculado como dois arquivos separados e conflitantes:

node_modules\@types\MyLib\index.d.ts(3,11): error TS2300: Duplicate identifier 'Foo'.
C:/MySolution/MyLib/bin/npm/@types/index.d.ts(3,11): error TS2300: Duplicate identifier 'Foo'.

Se eu copiar os arquivos manualmente em vez disso, funcionará conforme o esperado. Posso contornar isso definindo typeRoots: ["./node_modules/**/"]

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

Questões relacionadas

DanielRosenwasser picture DanielRosenwasser  ·  3Comentários

weswigham picture weswigham  ·  3Comentários

uber5001 picture uber5001  ·  3Comentários

fwanicka picture fwanicka  ·  3Comentários

siddjain picture siddjain  ·  3Comentários