Typescript: Déclarations de type en double avec lien npm

Créé le 15 janv. 2016  ·  147Commentaires  ·  Source: microsoft/TypeScript

Utilisation de TypeScript 1.7.3.

Supposons que j'ai les packages npm ci-dessous.
Les fichiers de déclaration sont générés par le compilateur TypeScript et référencés à partir des autres packages au moyen de la manière décrite ici .

paquet-un

ts src:

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

déclaration ts:

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

package-b (dépend du package-a):

ts src:

import ClassA from 'package-a';

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

déclaration ts:

import ClassA from 'package-a';

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

package-c (dépend de package-a et package-b):

ts src:

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

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

La dernière ligne provoque une erreur lors de la compilation:

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

Lorsque je supprime la ligne private foo; de la déclaration de package-a, TypeScript n'émet aucune erreur.
Cependant, cette solution de contournement est un peu douloureuse.

Je comprends que l'exposition des propriétés privées à la déclaration est intentionnelle (https://github.com/Microsoft/TypeScript/issues/1532).
Je pense que TypeScript devrait ignorer les propriétés privées lors de la compilation de l'affectation de variables.
Ou y a-t-il une meilleure solution de contournement pour cela?

@types Bug Fixed

Commentaire le plus utile

Je viens de fusionner un changement qui tentera de détecter les paquets en double en fonction de leur nom et de leur version, et n'en utilisera qu'un. Essayez-le avec typescript@next lors de sa prochaine publication.

Tous les 147 commentaires

Il n'y a qu'une seule déclaration racine de ClassA ici, donc cette erreur ne devrait pas se produire.

Eh bien, désolé, j'ai trouvé que cela est lié à npm link .

Lorsque j'utilise npm link , les packages sont installés comme ci-dessous, car il crée simplement des liens symboliques.

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

Comme indiqué, il semble qu'il existe deux fichiers de déclaration différents pour package-a.
Si j'installe des packages normalement en utilisant npm install , cela ne se produit pas car la déclaration de package-a n'est pas incluse dans package-b dans ce cas.

J'espère qu'il y aura de toute façon une solution à cela, mais cela pourrait être difficile et peu prioritaire.

J'ai fini par ne plus utiliser npm link , et cela n'a plus d'importance pour moi.

Très bien, mais quelqu'un d'autre pourrait: cligner de l'œil:

il y a en fait deux fichiers sur le disque avec deux déclarations de ClassA. donc l'erreur est correcte. mais nous devons tenir compte des modules de nœuds lorsque nous comparons ces types. ce problème a déjà été signalé dans https://github.com/Microsoft/TypeScript/issues/4800 , pour Enums, nous avons changé la règle en une vérification semi-nominale. faire éventuellement la même chose pour les classes.

+1 à ce sujet avec TS 1.7.5 avec tous les packages pertinents liés à NPM. J'ai essayé de construire un cas de test qui présente le problème mais je n'ai pas pu. Peu importe ce que j'ai essayé, TS était bien avec le scénario que je vois échouer avec TS2345 dans mon application, et pour autant que je sache, toutes les copies du fichier .d.ts problématique étaient des liens symboliques vers le même fichier, donc il ne devrait pas ont eu des déclarations différentes au sein du type. Ce serait bien cependant si l'erreur émise par Typescript faisait référence aux fichiers qui ont déclaré les deux types incompatibles, car cela pourrait faire la lumière sur quelque chose que je ne considère pas. À l'heure actuelle, il indique qu'il existe deux définitions mais ne fait rien pour aider le développeur à identifier le problème.

Pour contourner ce problème, vous pouvez utiliser <any> sur l'expression en conflit pour ignorer la vérification de type. Évidemment, cela peut vous obliger à faire une autre annotation de type là où vous n'auriez peut-être pas eu à le faire auparavant. J'espère que quelqu'un pourra isoler ce problème à un moment donné.

EDIT: a précisé que le lien NPM est en jeu dans mon cas

Remarqué TS 1.8 est disponible, mis à niveau et le problème existe toujours dans cette version.

Merci pour tout le travail d'analyse et de documentation de ce problème. Nous avons le même problème dans certaines de nos bases de code. Nous avons porté certains projets pour utiliser correctement les dépendances package.json mais nous voyons maintenant cela lors de l'utilisation de npm link pendant le développement.

Puis-je vous aider à résoudre ce problème?

J'utilise Lerna qui lie les packages autour et vois le problème là aussi. Typecript version 2.0.3.

Malheureusement, Lerna et ses liens symboliques sont une exigence absolue, j'ai donc utilisé cette mauvaise solution de contournement pour que cela compile correctement tout en étant correctement vérifiable par les consommateurs:

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

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

La classe est très petite, donc ce n'était pas si ardue, et je ne m'attends pas à ce qu'elle change vraiment jamais, c'est pourquoi je considère cela comme une solution de contournement acceptable.

FYI, je me suis également retrouvé ici en raison de l'utilisation de npm link et de cette erreur. Quelqu'un at-il trouvé une solution de contournement pour cela?

@xogeny pouvez-vous expliquer comment le lien npm cause ce problème pour vous?

@mhegazy Eh bien, j'ai commencé à avoir ces erreurs comme celle ci-dessus (sauf que j'utilisais Observable de rxjs , c'est-à-dire que "Type 'Observable' n'est pas assignable au type 'Observable'). Ceci, bien sûr, cela semblait étrange parce que les deux auxquels je faisais référence Observable partir d'exactement la même version de rxjs dans les deux modules. Mais là où les types se "rencontraient", j'ai eu une erreur. J'ai fouillé et a finalement trouvé ce problème où @kimamula a souligné que si vous utilisez npm link , vous obtiendrez cette erreur. Comme d'autres, j'ai contourné ce problème (dans mon cas, j'ai créé une interface en double de la fonctionnalité que je nécessaire dans un module, plutôt que des références rxjs ).

Est-ce que ça répond à votre question? Je demande parce que je ne pense pas que mon cas semble différent des autres ici, donc je ne suis pas sûr que cela vous aide.

Nous avons travaillé dans TS2.0 spécifiquement pour activer les scénarios npm link (voir https://github.com/Microsoft/TypeScript/pull/8486 et # 8346). Avez-vous un exemple où je peux voir où le lien npm ne fonctionne toujours pas pour vous?

Huh. J'utilise la version 2.0.3 (j'ai vérifié). Je vais essayer de créer un cas reproductible.

À propos, vous devriez suivre ces discussions car elles impliquent que c'est toujours un problème à partir de TS 2.0:

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

Le problème que je vois dans mon dépôt Lerna est quelque peu impliqué, alors j'en ai fait une version allégée à https://github.com/seansfkelley/typescript-lerna-webpack-sadness. Cela pourrait même être la faute de webpack / ts-loader, donc j'ai également déposé https://github.com/TypeStrong/ts-loader/issues/324 là-bas.

J'utilise typescript 2.0.3 et je vois cette erreur avec Observable comme décrit ci-dessus, par exemple

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>'.

Je frappe également cela dans un package Lerna monorepo. Il semble que la plupart des parties du système de types, mais pas toutes, utilisent le realpath pour identifier de manière unique les fichiers. Si vous descendez la branche qui utilise le chemin du lien symbolique plutôt que le chemin réel, vous vous retrouverez avec des types identiques mais différents.

C'est un problème assez brutal qui n'affectera que les bases de code plus complexes, et il semble impossible de contourner sans prendre des mesures drastiques, alors j'espère pouvoir vous convaincre tous de lui accorder l'attention qu'il mérite. 😄

C'est plus visible dans les cas où vous avez une application qui dépend de la dépendance A, la dépendance A dépend de la dépendance B et vend des objets qui contiennent des types de la dépendance B.L'application et la dépendance A à la fois npm link Dépendance B et s'attendent à être capable d'en importer des types et de leur faire décrire la même chose.

Cela entraîne des messages d'erreur profonds, et je suis sur le point de passer en revue et d'éliminer toutes les propriétés private et protected dans mes bibliothèques car j'ai déjà perdu tellement de temps à cela :

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)

Je vous remercie tous vraiment de regarder cela; Je vous remercie!

@tomdale utilisez-vous Webpack, tsc ou un autre outil de construction? Mon problème semble ne se produire que lors de la compilation via Webpack (voir le référentiel lié de mon commentaire précédent ).

@seansfkelley Cela ressemble à https://github.com/TypeStrong/ts-node.

C'est vrai, il utilise ts-node (pour l'application racine). Les dépendances, cependant, sont des packages compilés avec tsc .

Je viens de rencontrer ce problème et c'est un problème majeur pour nous car nous essayons de diviser notre back-end en plusieurs petites bibliothèques. Pendant le développement, nous avons souvent besoin de npm lier nos dépôts. Le problème spécifique que j'ai rencontré et qui m'a incité à trouver ceci est l'utilisation des observables et des interfaces rxjs:


// 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({});
    }
}

Cela fonctionne si je ne le fais pas npm link , mais quand je le fais, j'obtiens:

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>'.

La seule suggestion que je puisse faire est d'éviter private . Je ne publie plus de packages avec private cause de ce problème et j'utilise simplement les préfixes de style JavaScript _ place. Je l'ai rencontré avec https://github.com/Microsoft/TypeScript/issues/7755, qui est une discussion similaire sur la raison private laquelle npm link ).

@blakeembrey quand vous dites éviter le privé, suggérez-vous que je puisse changer quelque chose dans mon code? Je suppose que la définition de type Observable est le problème, non?

@jeffwhelpley Oui, désolé, vous Observable . Malheureusement , l'éviter private conseil est très mince et n'a pas été tout à fait applicable à vous 😄 Peut - être que vous pouvez faire une question sur, je suppose, rxjs sur l'utilisation de private dans leurs interfaces publiques?

Edit: J'ai surtout commenté parce que j'avais suivi le problème plus tôt et évité de me joindre à mes propres expériences, mais je pensais que je pourrais aussi écrire mes pensées à nouveau au lieu de cela, elles sont similaires à https://github.com/Microsoft/TypeScript/issues/ 6496 # issuecomment -255232592 (où @tomdale suggère d'éliminer private et protected , j'ai fait la même chose il y a quelque temps).

J'ai eu l'impression de @mhegazy qu'il pensait qu'il n'y avait aucun problème avec npm link . Mais cela semble encore nous tourmenter, nous et les autres. Je ne sais donc pas où se situe ce problème? Est-ce un problème reconnu avec TS 2.0+ ou est-ce que je manque juste une solution de contournement quelque part?!?

J'obtiens ce même problème et il ne semble pas être causé par npm link . Je l'obtiens toujours si je l'installe en utilisant npm install file.tar.gz . Voici l'erreur:

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>'.

Voici à quoi ressemble mon 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);
  }

Il se plaint de la ligne this.user$ . Stormpath a user$ défini comme suit:

@Injectable()
export class Stormpath {

  user$: Observable<Account | boolean>;

@xogeny Odd, je crois comprendre que l'identité de la définition était liée à l'emplacement du fichier, ce qui signifierait qu'ils vont toujours causer des problèmes en utilisant npm link (car la dépendance npm link ed aurait ses propres dépendances installées) . Peut-être que l'identité de la définition a été modifiée - l'utilisation de hachages de fichiers pourrait être une bonne solution de contournement dans TypeScript. Malheureusement, il n'y a qu'une douzaine de façons différentes de se retrouver avec des modules en double dans JavaScript ( npm install de GitHub, npm install , clones manuels, les conflits de version peuvent même entraîner l'atterrissage de la même version à différents emplacements comment fonctionne l'algorithme de résolution du module du nœud, etc.).

@blakeembrey Peut-être. Mais alors de quoi s'agissait - il?

Remarque, je ne me plains pas. J'essaie simplement de savoir s'il y a un espoir que cela soit résolu ou non. C'est une épine sérieuse dans notre côté pour toutes les raisons mentionnées par @jeffwhelpley .

@xogeny Je sais, j'essaye aussi, j'aimerais le voir résolu correctement 😄 J'ai lu les problèmes liés, mais ils sont tous conçus pour résoudre le chemin réel d'un lien symbolique qui implique si vous avez deux (vrais) fichiers ils seront toujours en conflit car ils seront résolus à différents endroits. C'est ce qui se passe lorsque vous npm link d'un projet à un autre car les deux auraient leurs propres dépendances qui peuvent différer avec les symboles réexportés du package npm link ed.

Edit: je peux confirmer, tous les problèmes sont dus à deux fichiers. npm link le déclencherait car il est simple d'avoir une dépendance dans un dépôt que vous venez de lier qui est la même dépendance que dans le projet auquel vous avez lié. Une simple repro serait de faire un npm install de la même dépendance à deux niveaux différents d'une application et de surveiller les erreurs.

image

À tous ceux qui suivent ce fil ... J'ai essayé la solution de contournement décrite ici et cela semble fonctionner (jusqu'à présent).

J'ai reproduit cette erreur.

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

Puisqu'il y a deux installations de rxjs , on obtient:

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>'.

J'ai une solution de contournement qui fonctionne très bien pour la ligne de commande, mais Visual Studio est toujours tout foiré: https://github.com/Microsoft/TypeScript/issues/11107#issuecomment -254003380

ma nouvelle solution de contournement pour Windows + Visual Studio 2015 consiste à copier automatiquement mes dossiers xlib Library src et dist dans les dossiers node_modules\xlib\src et node_modules\xlib\dist du projet consommateur.

voici la partie importante de mon script de fichier de commandes robocopy si quelqu'un le souhaite:

: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

Désolé d'avoir à nouveau buggé avec ce problème, mais c'est un sérieux frein pour notre projet de ne pas pouvoir faire npm link pendant que nous apportons des modifications. J'adorerais aider avec un PR si l'un des contributeurs actuels de TypeScript pouvait me donner un petit guide sur où commencer à chercher dans la base de code.

J'ai aussi du mal avec celui-ci. Nous avons adopté TS à partir d'une petite application, maintenant nous l'avons divisé en sous-modules et les avons liés et… BOOM. TS ne compilera plus. Est-ce toujours un problème dans tous les dist-tags TS? Je rencontre actuellement ce problème dans @rc (2.1.1).

@heruan et @jeffwhelpley pouvez-vous typescript@next , nous avons corrigé quelques problèmes connexes. et si vous rencontrez toujours le problème, veuillez fournir plus d'informations sur la configuration de votre projet.

@mhegazy Je suis sur Version 2.2.0-dev.20161129 et j'ai toujours le problème. Le problème spécifique est que j'ai un projet (appelons-le ProjectA) qui contient une «interface» (en utilisant une classe, mais c'est pour que je puisse utiliser la classe comme jeton pour Angular 2 DI) comme suit:

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

Ensuite dans un projet complètement séparé (appelons-le ProjectB) qui a une classe qui implémente l'interface du premier projet comme ceci:

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
}

Lorsque je fais une compilation dactylographiée normale pour ProjectB, cela fonctionne bien. Mais si je npm link ProjectA depuis le répertoire racine de ProjectB et que je lance à nouveau tsc , j'obtiens:

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>'.

Je ne pouvais pas répliquer dans un projet simulé, je suppose que je manque la cause du problème, donc je suis incapable de le répliquer. @jeffwhelpley pouvez-vous publier un projet simulé reproduisant le problème? Je pense qu'un projet Lerna devrait être bien et facilement testable.

@heruan J'essaierai de configurer cela.

Un, pour info, cependant. Je pense que j'ai peut-être trouvé une solution. Le problème est résolu si I npm link rxjs à la fois dans ProjectA et ProjectB. Cela a du sens car dans ce cas, ProjectA et ProjectB utilisent les mêmes fichiers rxjs exacts. Sans cela, ils utilisent techniquement des fichiers différents (même si la même version):

Si vous venez de npm link ProjectA de ProjectB, alors:

  • ProjectB pointe vers node_modules / rxjs
  • ProjectA existe en tant que lien symbolique dans node_modules / ProjectA et les rxjs auxquels il fait référence se trouvent dans node_modules / ProjectA / node_modules / rxjs

Mais si vous npm link rxjs dans les deux, ces deux références rxjs seront liées symboliquement au même emplacement npm exactement global.

Quoi qu'il en soit, ce n'est évidemment toujours pas idéal, mais au moins quelque chose qui peut nous faire avancer.

Aussi ... je ne sais pas si cela est pertinent ou important (je le verrai une fois que j'ai mis en place le projet de test), mais mes deux bibliothèques (c'est-à-dire ProjectA et ProjectB) sont en fait des dépôts npm privés.

Merci @jeffwhelpley pour l'indice, mais comme j'utilise Lerna, tous les modules sont déjà liés les uns aux autres, ils lisent donc le même fichier, mais je pense que le compilateur TS prend en compte le chemin du lien et non le vrai. Je me trompe peut-être, car je ne peux pas reproduire sur un projet simulé, et je suis vraiment en train de devenir fou…

Quelqu'un ici est-il capable de résoudre ce problème de manière élégante?

Notez également que ce n'est pas seulement un problème avec npm link , vous rencontrerez également ce problème sur les versions de production, lorsque vos dépendances partagées pointent vers une version différente.

c'est à dire. ProjectA a besoin de [email protected] et ProjectB utilise [email protected]

Lorsque vous installez ProjectA en tant que dépendance dans ProjectB, vous aurez également des types dupliqués, car il y aura par exemple deux déclarations Observable , une dans node_modules/rxjs et une dans node_modules/project_a/node_modules/rxjs

Vous pouvez contourner ce problème en autorisant la version rxjs dans ProjectA à être quelque chose comme ~4.9.0 , de sorte que npm install n'a pas besoin de télécharger sa propre version et utilisera à la place la version ProjectB. Mais gardez à l'esprit qu'il ne s'agit pas uniquement d'un problème de flux de travail de développement.

Publier ici selon la suggestion de @ andy-ms. Je l'ai réessayé hier avec la dernière version 2.0.x et je l'ai toujours.

J'obtiens cela avec les typages pour Angular 1: https://github.com/DefinatelyTyped/DefinatelyTyped/issues/10082#issuecomment -253023107

Ran dans ce encore aujourd'hui, en particulier le problème avec les liens symboliques. Ma configuration est quelque chose comme ceci:

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

Si j'ai juste @types/angular , tsc fonctionne bien. Si j'ai toute la suite ( @types/angular-{animate,cookies,mocks,resource,route,sanitize} ), je commence à recevoir des tas d'erreurs de type:

$ 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'.

Je l'ai corrigé en ajoutant la base ../../node_modules/@types comme typeRoots à mon tsconfig.json :

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

J'ai essayé d'ajouter le node_modules/@types local, mais cela n'a pas fonctionné.

@heruan un hack que j'ai commencé à faire est d'implémenter mon propre script npm pour lier / dissocier au lieu d'utiliser la fonctionnalité lerna. Donc, vous pouvez faire quelque chose comme lerna run link , puis dans tous vos fichiers package.json, vous avez un script npm appelé link qui fait tous les liens npm, y compris (dans mon cas) npm link rxjs . Cela semble fonctionner correctement, pas certainement pas idéal.

@jeffwhelpley pouvez-vous partager votre solution ici?

@yvoronen Je ne peux pas partager tout mon code, mais ma solution est décrite ci-dessus. À un niveau élevé, la clé que j'ai trouvée est d'être sûr de lier npm non seulement tous les projets locaux sur lesquels vous travaillez, mais également de lier npm les bibliothèques externes qui peuvent être à l'origine du problème (dans mon cas, rxjs est le problème à cause du private vars dans l'objet Observable). Donc, j'utilise lerna pour gérer tous mes projets locaux, puis lerna run link . Sous les scènes, cela appelle npm run link dans chacun des dossiers racine de mon projet. Donc, vous devez avoir le script link défini dans votre package.json comme ceci:

  "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"
  }

J'espère que cela a du sens, mais faites-moi savoir si vous avez des questions.

Je voulais fournir une mise à jour. D'un échange désinvolte que j'ai eu avec

  • Une solution que nous considérons le concept de la distinction des packages en fonction de leur version ainsi que de leur nom de résolution. Je n'ai pas tous les détails sur ce que cela impliquerait.
  • Une autre consiste simplement à étendre complètement le chemin pour obtenir la «vraie» identité d'un lien symbolique. Je pense que c'est plus simple, mais plus limité lorsqu'il s'agit de traiter le même paquet dans différentes versions, mais cela aide à résoudre un nombre décent de cas.

Êtes-vous sûr que votre commentaire appartient à ce numéro? Ça sonne complètement
différent.

Le jeu.12 janvier 2017 à 03:14, Nikos [email protected] a écrit:

Remarque, je n'utilise pas de types ou de lien npm AFAIK.

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

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, affichez-le sur GitHub
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment-272137732 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAUAmcMXodOvU7coymMqGzTofD4pMagpks5rRgsogaJpZM4HFcWl
.

@dobesv, c'est en fait toute la raison pour laquelle vous voyez le problème en premier lieu. TypeScript reconnaît la déclaration de classe comme deux déclarations distinctes car il ne pouvait pas distinguer le chemin lié symboliquement du vrai chemin. La solution est soit de

  1. Développez le lien symbolique.
  2. Vérifiez si le package contenant est le même.

@DanielRosenwasser Désolé, mon commentaire était une réponse au commentaire de quelqu'un d'autre "Le jeu, 12 janvier 2017, 03:14 AM Nikos @ . * > A écrit" ... qui c'est et ce qu'ils ont dit Je ne me souviens plus, je crois qu'ils demandaient un problème dans ce fil de commentaires, qui n'avait rien à voir avec le lien npm.

Mais pendant que je suis ici, je dois mentionner qu'il y a quelque chose d'amusant dans la façon dont le nom de fichier joue un rôle dans les types. Aujourd'hui, j'ai eu un problème avec RxJS où il se plaignait que telle ou telle méthode n'était pas définie sur Observable. La raison en était que la bibliothèque HTTP avait sa propre copie privée de rxjs qui était différente de tout le monde. En fait, j'ai trouvé quatre copies différentes de rxjs dans mon arbre node_modules.

Cela semble être une approche problématique qui continuera à être problématique et déroutante.

Si tout ce concept de nom de fichier jouant un rôle dans l'identité d'un type disparaissait, je pense que ce problème de lien npm disparaîtrait également.

Je suis encore un peu flou sur la façon dont cela fonctionnerait ... Je suis nouveau dans TypeScript. Mais c'est un peu l'impression que j'ai, c'est que cette chose "le nom de fichier compte" m'a causé une certaine confusion en conjonction avec les bibliothèques que j'utilise (ionic2 et angular2 et rxjs).

Eh bien, le problème est que le nom de fichier est toujours l'identité d'un module en Javascript, il ne peut donc pas disparaître complètement. Quelqu'un peut-il expliquer quels sont les problèmes liés à l'utilisation du chemin canonique (résolution du lien symbolique) en ce qui concerne plusieurs versions de package? S'il existe plusieurs versions de packages dans une arborescence, elles auront plusieurs chemins absolus canoniques, n'est-ce pas?

EDIT: J'ai réalisé cela après avoir posté, et ce commentaire le résume bien:
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -257016094

exclude et compilerOptions.typeRoots sont complètement ignorés par tsc. J'ai essayé toutes les combinaisons pour ignorer les chemins liés par un lien symbolique, mais ce ne sera tout simplement pas
il voit le module comme un chemin complètement différent, comme s'il résout le lien symbolique et qu'il ne comprend pas les modèles exclus.

par exemple, j'ai G:\www\cim-service-locator npm lié à npm link cim-service-locator . sur le chemin de mon projet dans G:\www\cim-backend , les erreurs s'affichent comme ceci:

crop

J'ai essayé toutes les combinaisons possibles d'exclusions / inclus / typesRoot mais je n'ai pas pu faire en sorte que tsc les ignore. en utilisant 2.2-dev.20170131

Nous avons rencontré ce problème à la fois en utilisant "npm link" (via un problème SPFx signalé par @waldekmastykarz) et aussi sans "npm link" (voir bug # 11436).

J'ai finalement réalisé que la rigueur du compilateur TypeScript était due à des incompatibilités qui peuvent se produire de manière réaliste en raison de la conception farfelue du dossier node_modules . Prenons cet exemple:

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]

Dans cet exemple, B @ 2 doit être installé dans les sous - dossiers afin d' éviter un conflit avec la dépendance de A sur B @ 1 . Maintenant, supposons que ClassB s'étend de ClassE, et nous avons quelque chose comme ceci:

B / package.json

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

Si package.json de C demande [email protected] , alors les deux copies de ClassB peuvent se retrouver avec des implémentations de classe de base différentes, ce qui signifie qu'elles sont en fait incompatibles. Le code peut échouer à l'exécution si vous essayez de les utiliser de manière interchangeable.

Dans cet exemple, TS2345 éviterait cette erreur, ce qui est bien. Cependant, ce n'est PAS essentiel: si le compilateur traitait les deux copies de ClassB comme équivalentes, son système de types serait toujours cohérent en interne et aurait un comportement déterministe.

Ceci est important car pour nous TS2345 produit principalement de fausses alarmes. Ces fausses alarmes obligent les gens à écrire «comme n'importe quel» partout où ils partagent des types entre les packages NPM, ce qui provoque d'autres erreurs. La rigueur crée donc plus de problèmes qu'elle n'en résout.

Je voudrais proposer le correctif suivant:

Si TOUTES ces conditions sont remplies, ne déclarez PAS TS2345 pour les classes avec des membres privés:

  1. Les signatures publiques sont compatibles selon le typage canard TypeScript habituel
  2. Les classes sont définies dans des dossiers de packages NPM avec le même nom et la même version (selon package.json)
  3. Les classes ont le même chemin relatif pour leur module (par exemple "./lib/blah/Bdts")

Si l'un de ces critères n'est pas respecté, vous pouvez signaler TS2345.

@iclanton @ nickpape-msft

L' erreur

Salut les gars,
Quelqu'un a trouvé une solution ??
J'ai le même problème lorsque je lie un projet avec un autre avec RxJS.
Merci ;)

Salut, une solution temporaire consiste à envelopper les Observables retournés par une dépendance avec Observable#from .

Pas encore de solution. ?

Il semble y avoir deux problèmes ici.

Les utilisateurs de ts-loader obtenant des erreurs erronées pour les définitions en double, semblent être causés par une entrée non valide dans l'API du compilateur. Un correctif pour cela est disponible dans TypeStrong / ts-loader # 468.

L'autre problème est si vous avez le même package (même package npm + version) installé deux fois localement sur le système de fichiers (sans utiliser npm link ) dans deux dossiers imbriqués, avec des Enums ou des classes avec des membres privés, en comparant les les types de ces deux packages échoueraient car incompatibles.
Ce problème est un peu plus complexe et nécessitera un travail supplémentaire pour le compilateur pour "dédupliquer" les packages avant de les traiter.

Si aucune de ces deux catégories ne s'applique à vous, veuillez déposer un nouveau problème et nous fournir suffisamment d'informations pour reproduire le problème localement, et nous serons heureux d'enquêter plus avant.

Une solution de contournement connue consiste à utiliser une solution multi-projets qui éliminera les dossiers en double, c'est-à-dire en veillant à ce que les deux sous-dossiers node_modules soient liés par un lien symbolique vers la même cible.

Rush (que nous utilisons) et Lerna en sont des exemples.

@smcatala Vous pouvez expliquer votre solution. J'ai besoin de le réparer de toute urgence. Merci.

@ leovo2708
module 'foo':

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

code client dans un autre module, qui dépend du module 'foo':

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

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

@ leovo2708 la solution simple est de ne pas utiliser npm link .

en utilisant ts 2.1, j'ai pu utiliser le lien npm avec une seule bibliothèque (appelons-le xlib , qui est mon vrai exemple) mais vous devrez vous assurer que les modules que votre bibliothèque ( xlib charges

Je fais cela par le flux de travail suivant

  1. supprimer node_modules
  2. npm link xlib qui crée la sym_link à xlib dans mon projet de consommation node_modules
  3. npm install qui installe le reste des dépendances de mon projet consumign

Je n'ai pas vraiment suivi cette conversation ni vérifié si ce problème avait changé / modifié depuis la version 2.2, mais je partagerais simplement ma solution de contournement pour ts 2.1

Au cas où cela serait utile, j'ai rassemblé une repro minimale des multiples définitions de cas enums ici: https://github.com/rictic/repro-npm-link-typescript-issue

@mhegazy Nous voyons le problème ci-dessus lors de l'utilisation du lien npm, bien que je ne pense pas que cela affecte le reste de votre analyse.

Merci beaucoup, j'espère que cela sera corrigé bientôt. Cependant, j'ai utilisé une nouvelle solution, dupliquer tous les fichiers en utilisant Observable. Ce n'est pas bon mais seulement une solution temporaire.

tsconfig.json expose un mappage de chemin, ajoute des dépendances dupliquées dans paths , donc il sera chargé à partir de la droite node_modules au lieu d'une liée.

{
  "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"]
    }
  }
}

Je ne sais pas si mentionné ici déjà, mais cette solution a fonctionné pour moi: https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001

C'est fondamentalement la même chose que la solution de @charpeni ci-dessus, sauf sans le préfixe "../" dans les chemins. (ce qui semble étrange, car cela ne signifierait-il pas que le fichier tsconfig.json serait dans un sous-dossier de la racine du projet?)

C'est une excellente idée @charpeni. J'ai utilisé ce paramètre de chemins pour contourner divers autres problèmes similaires, mais il semble également idéal pour celui-ci. En fait, je me demande si le bon paramètre paths dans le projet consommateur (plutôt que dans chaque projet consommé) pourrait distraire le compilateur TypeScript de la résolution des nœuds suivants. Si cela fonctionne, ce serait un hack O (1) au lieu d'un hack O (n). Essentiellement, un tel schéma exécuterait la résolution de nœud de manière statique, puis remplirait les résultats dans tsconfig.

J'expérimente ces choses de manière semi-publique si quelqu'un veut regarder (ou aider ...). J'essaierai probablement l'idée ci-dessus ensuite.

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

Pour une utilisation plus facile, vous pouvez également définir les chemins comme celui-ci:

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

Le lien npm est une partie cruciale du flux de travail lorsque vous travaillez avec plusieurs packages par opposition à une architecture mono-repo. TS devrait être capable de voir que les deux packages sont identiques et pas d'erreur

@charpeni Je n'ai pas pu faire fonctionner la solution de contournement. Pour être clair, à quel tsconfig.json cela doit-il être ajouté? Le package racine ou le package lié?

Je rencontre également ce problème. Cela a soudainement commencé à se produire lundi, et je ne sais pas pourquoi. Cela entrave vraiment le développement, en particulier lorsqu'il s'agit de développer des packages pour nos projets. J'ai essayé de nombreuses solutions de contournement pour résoudre ce problème. L'exécution de mklink /j sous Windows provoque toujours ce problème, il ne s'agit donc pas d'un problème de lien npm. Si quelqu'un a une solution de contournement ou une solution, ce serait d'une grande aide.

Ma solution de contournement consiste à lier npm à chaque package "dupliqué" à la fois dans le package racine et dans la dépendance, car ils font à nouveau référence aux mêmes fichiers.

Btw, ce problème n'a rien à voir avec @types

Nous avons fini par utiliser le modèle glob.

@felixfbecker Pour l'implémentation, il est disponible ici: https://github.com/sherweb/ng2-materialize/blob/master/demo-app/tsconfig.json#L19 -L22

J'ai un problème similaire sauf qu'il est entièrement lié à @ types / node.

libA dépend de @ node / types
libB dépend de libA et @ node / types
libC dépend de libA, libB et @ node / types

libA se construit bien.
libB npm lié au fichier de builds libA.
libC npm lié à libA et libB échoue à la vérification de type avec des erreurs telles que

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'.

J'ai essayé de jouer avec "types" et "typeRoots" sans succès.

@charpeni Il semble que votre projet dépende également de @ types / node. Avez-vous un aperçu de la solution à mon problème ou d'une solution de contournement?

@nicksnyder cela peut être dû au fait qu'il s'agit de versions différentes, et @types/node est une déclaration globale, ce qui signifie que vous ne pouvez pas définir deux fois les mêmes noms. C'est la raison pour laquelle il est préférable que les packages ne dépendent pas des typages environnementaux, ceux-ci doivent être fournis par l'utilisateur:
https://github.com/Microsoft/types-publisher/issues/107

@nicksnyder J'ai eu un problème similaire et j'ai pu le contourner en liant les trois projets à une seule installation @ types / node. Les définitions étant alors définies dans le même fichier, elles ne sont plus des doublons

@felixfbecker J'ai vérifié que tous les projets dépendent de la même version de node.

FWIW libA est https://github.com/Microsoft/vscode-languageserver-node/tree/master/jsonrpc , libB est https://github.com/Microsoft/vscode-languageserver-node/tree/master/client et libC est ma propre extension VS Code.

@uncleramsay comment avez-vous exactement npm link @types/node ?

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

Je voudrais faire la solution de liaison, mais j'ai également piraté cela en supprimant la dépendance @ types / node dans libA et libB, et j'ai ajouté un refs.d.ts qui contient des références locales à la copie de node de libC.

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

J'ai trouvé que j'étais en mesure de résoudre les problèmes que j'avais à partir de la description dans le commentaire dans https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -225303098

nous avons seulement ajouté la prise en charge de la résolution des liens symboliques pour les modules ...

À des endroits distincts dans la base de code lorsque nous utilisions deux styles de référence différents:

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

Ces deux sont incompatibles dans le cas où node_modules est lié symboliquement, car la résolution du module (avec types= ) est étendue au chemin réel, mais path= ne l'est pas. Il en résulte deux fichiers différents référencés lors de la compilation avec tsc --listFiles , le lien symbolique et le chemin réel.

La solution que nous avons choisie était d'utiliser l'un ou l'autre, mais jamais les deux. Cela a également aidé à spécifier le typeRoots: [] dans le tsconfig pour éviter que le compilateur charge automatiquement les types à partir de node_modules/@types dans le cas de l'utilisation du style reference path= .

Je crois que la préférence pour l'avenir (du moins pour nous) est de préférer le style types= .

Idéalement cependant, il serait préférable de développer le chemin réel dans le reference path= et de vérifier les chemins correspondants en double pour éviter de tels problèmes.

J'espère que cela aide quelqu'un.

@nicksnyder, vous devriez pouvoir faire quelque chose comme ceci:

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

De cette façon, B & C pointent exactement les mêmes fichiers que A.

@unclerams peut être conscient que ce sont alors toutes les mêmes versions, ce qu'elles n'ont peut-être pas été auparavant

Les dépendances entre pairs ne peuvent-elles pas être une solution pour cela?
http://codetunnel.io/you-can-finally-npm-link-packages-that-contain-peer-dependencies/

Les dépendances homologues ont été inventées pour une situation où un plug-in veut dire ce qu'il va avec. Ils fonctionnent en quelque sorte bien pour cette affaire. Mais ils causent beaucoup de problèmes si les gens commencent à convertir toutes leurs dépendances en dépendances homologues, dans l'espoir d'éviter la duplication "npm install".

Nous avons passé des mois à les bannir de nos dépôts git internes. Lorsqu'elles sont utilisées comme je pense que vous le suggérez, les dépendances entre pairs vous permettent de résoudre un problème de version côte à côte en l'échangeant contre plusieurs nouveaux problèmes:

  • l'arborescence entière est inversée, c'est-à-dire que chaque paquet devient maintenant responsable de prendre une dépendance dure sur les paquets qui étaient autrefois des dépendances indirectes, dans de nombreux cas sans aucune idée de ce à quoi cela sert

  • si une dépendance homologue est supprimée, ces dépendances matérielles ne seront probablement jamais supprimées

  • les auteurs de paquets sont tentés d'utiliser de larges gammes pour leurs modèles de versions homologues, prétendant travailler avec des versions contre lesquelles ils n'ont jamais réellement testé; les constructions cassées deviennent soudainement le problème du consommateur

Bien dit.

solutions de contournement

Voici 3 options pour les solutions de contournement que j'ai utilisées:

option 1: utiliser vscode pas Visual Studio

Le compilateur tsc est beaucoup plus indulgent que VS2017, probablement parce que VS2017 explore le code (y compris les liens symboliques node_modules ) pour fournir une belle intelligence et devient ainsi confus. Cependant, j'ai de gros projets complexes multi-modules npm, alors utilisez VS2017 ... alors lisez les options 2 et 3 si vous avez des besoins similaires ....

option 2: émettre d.ts

si vous utilisez outDir et rootDir (dans votre tsconfig.json ), votre lib-module lié symboliquement doit émettre des déclarations d.ts et ces déclarations doivent être dans le lib-module package.json types propriété.

voici un exemple de ce à quoi devrait ressembler le tsconfig.json de votre lib-module

{
  "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"
  ]
}

et le package.json votre lib-module devrait inclure quelque chose comme ce qui suit:

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

Cette option fonctionne bien, le principal problème est que dans Visual Studio lors du débogage ou "go-to-definition" ou "show all references", il vous montrera le d.ts pas les fichiers source du typographie, ce qui bat le principal avantage du studio visuel (navigation dans les grands projets)

si vous voulez voir un exemple réel de ceci dans la nature, regardez le module npm xlib v8.5.x

option 3: émettre .js ligne avec la source (mon choix préféré)

Vous pouvez utiliser vos fichiers .ts directement pour taper des modules lib liés par un lien symbolique! mais seulement si vous n'utilisez pas le fichier outDir`` and rootDir in your tsconfig.json ''. Cela permettra au référencement VS2017 de fonctionner correctement. Voici les paramètres de configuration dont vous avez besoin:

{
  "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"
  ]
}

et le package.json votre lib-module devrait être changé en:

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

mises en garde (choses qui ne fonctionneront pas avec l'option 3)

Les solutions de contournement ci-dessus ne fonctionnent que si chaque module de bibliothèque n'émet xlib exposer les définitions de type @types/async . Mais j'ai eu une autre bibliothèque qui faisait également référence indépendamment à @types/async . L'utilisation directe des fichiers .ts pour taper entraîne tsc à importer async partir de deux modules de librairie, ce qui le fait barf avec diverses formes de problèmes duplicate identifier . pour résoudre ce problème, vous devez soit ne pas importer le même @types partir de plusieurs modules de librairie, soit utiliser l'option 2 .d.ts solution

sommaire

J'espère que cela peut vous faire gagner les heures qu'il m'a fallu ... Dans l'ensemble, c'est extrêmement douloureux, et j'espère que l'équipe dactylographiée pourra réparer les modules liés par un lien symbolique. Mais au moins, cela fonctionne en quelque sorte maintenant (avant la version 2.x, c'était pratiquement impossible)

La solution de contournement publiée par @mhegazy dans https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001 (une variante de la solution de contournement 2 @jasonswearingen) a résolu ce problème pour nous lors de l'utilisation de modules liés dans un projet lerna!

Je pensais juste que je partagerais mon expérience ... en essayant de créer / extraire une bibliothèque d'un projet existant afin que la bibliothèque puisse être partagée entre d'autres projets.

Windows 10 Entreprise
VS 2015 mise à jour 3
Outils pour VS2015 2.2.2
Code VS 1.12.2
Typographie 2.2.2
NPM: 3.10.9
Nœud: 6.9.2

Nous avons un projet VS 2015 ASP.MVC avec un frontal Angular 4.1.x dont nous avons commencé à extraire certains composants pour créer une bibliothèque commune afin qu'ils puissent être utilisés dans d'autres projets.

Le projet de bibliothèque est construit à l'aide de VS Code et utilise le rollup pour créer les versions es2015, es5 et umd dans le dossier dist avec les fichiers d.ts appropriés.

Le résultat final ressemble à ceci:

-- 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

J'ai lié npm le dossier dist / mylib au dossier de mon projet VS 2015 / Angular 4.1.x.

Lorsque j'essaye de compiler le projet dans VS 2015, j'obtiens le même type de messages que ceux décrits dans certaines des situations ci-dessus pour Subscription, Observable, etc.

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

Si je supprime temporairement le répertoire node_modules du projet de bibliothèque, je reçois de nouvelles erreurs se plaignant de ne pas pouvoir trouver les modules:

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

Ce qui m'amène à la conclusion que lorsque le compilateur dactylographié compile l'application, il recherche effectivement dans le dossier node_modules du package my linked library les définitions de module pour ma bibliothèque et non le dossier applications node_modules.

Je ne sais pas quelle (s) solution (s) proposée (s) ci-dessus fournira une solution de contournement à ce problème, quelqu'un pourrait-il m'aider?

Merci!

@mikehutter Dans votre projet qui utilise votre bibliothèque (pas dans la bibliothèque elle-même), faites quelque chose comme ceci dans votre tsconfig:

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

Vous aurez peut-être besoin d'un léger ajustement en fonction de l'endroit où votre tsconfig et votre code source résultent.

(Comme d'autres dans ce fil, j'aimerais voir une amélioration de TypeScript qui rend cela inutile.)

@mikehutter, nous avons récemment ajouté des conseils dans Angular CLI pour travailler avec des bibliothèques liées, et il semble que dans votre cas, vous manquez la configuration des chemins TypeScript pour RxJs dans votre application grand public. Voir https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/linked-library.md pour plus d'informations.

@kylecordes est sur le point 👍

Merci @kylecordes et @filipesilva! C'était tout ce dont j'avais besoin ...

Salut!

@mhegazy , fortes chances que cela soit à nouveau retardé?
C'est vraiment pénible de contourner ce problème, obligeant chaque projet à toujours définir des mappages de chemin pour des choses dont il ne devrait vraiment pas se soucier.

En espérant vraiment cette fois que cela en fera la sortie!

Meilleur,

Ne pensez pas que cela a été mentionné pour le moment, mais la manière très rapide de contourner ce problème est:

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

L'entrée paths ci-dessus dit essentiellement: pour n'importe quel module, recherchez-le d'abord dans le dossier node_modules à la racine du projet, puis revenez à la règle normale (marche récursive dans les répertoires d'où l'importation a eu lieu).

(Veuillez me corriger si je me trompe, je suis encore un nouveau venu dans TS).

L'entrée dans paths semble être relative au baseUrl . Donc, si vous définissez baseUrl comme étant dans un sous-dossier, vous devez modifier la définition de vos chemins en conséquence. Par exemple:

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

@fiznool fyi qui fait partie de mes solutions de contournement options 2 et 3 (dans mon article ci-dessus). J'ai vu que la simple définition de la propriété paths n'est pas suffisante si vous avez des projets liés par un lien symbolique qui utilisent les mêmes typages.

@jasonswearingen votre message est beaucoup plus complet que le mien ... merci d'avoir clarifié cela. Je ne manquerai pas d'y revenir si je rencontre d'autres problèmes. 😄

Nous voyons cela également dans les projets Google. Comme décrit ici:
https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -306969543

Les solutions de contournement décrites ci-dessus en utilisant baseUrl et les chemins ne semblent pas fonctionner, tsc récupère toujours les définitions en double et aucune combinaison de chemins / baseUrl / include / exclude / etc. a su le convaincre du contraire.

Je suis curieux de savoir comment cela fonctionne normalement, si vous avez un projet qui dépend de X, et dépend également de Y qui dépend transitivement de X, comment tsc évite-t-il de charger les définitions de type deux fois?

@esprehn, je vous recommande vivement de lire mon message de contournement ici: https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -302886203

concernant ce lien, mes solutions (2 et 3) nécessitent plus que la simple définition de baseUrl et des chemins, donc si c'est tout ce que vous faites, veuillez relire. la solution "facile" est la solution 2, mais ma préférence est la solution 3 car elle permet une bonne "navigation vers la définition" via visual studio. le problème avec la solution 3 est que vous ne devez avoir les définitions externes .d.ts chargées qu'une seule fois dans la chaîne de dépendances.

J'espère que ça t'as aidé.

+1 J'utilise lerna et une sous-dépendance avec des typages inclus est signalée comme "dupliquée" lorsqu'elle est incluse via des dépendances liées.

Je peux partager du code si nécessaire.

Avec WebPack comme dans Angular-CLI, faites référencer ce package.json Angular-CLI au package RXJS , puis supprimez le package `RXJS 'du package.json de tout autre projet dont vous n'avez pas besoin à cause du WebPack .

Cette situation peut se produire non seulement avec des liens symboliques, mais avec npm-shrinkwrap.json dans une dépendance avec @types/node in dependencies . Shrinkwrap fait que npm installe deux versions identiques de @types/node dans le paquet parent et dans le paquet rétracté. Veuillez consulter https://github.com/KingHenne/custom-tslint-formatters/issues/5

Également rencontré ce problème lors de l'utilisation d'un projet react sur lequel @types/react installé et de le lier à une application qui utilise également @types/react

J'avais le même problème en travaillant avec des packages yarn link .
Rx.js lançait une erreur: 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>'

Heureusement, je l'ai résolu en utilisant la même version Rxj.s dans les packages parents et liés.
Donc, dans mon cas, deux versions différentes de Rx.js causé le problème.

C'est un énorme bloqueur lorsque vous travaillez avec des monorepos. J'espère vraiment que cela ne sera plus retardé et trouvera son chemin dans 2.5.

Modifier: 😮

image

Intéressant. Monorepo est le seul scénario dans lequel mon équipe ne rencontre PAS ce problème, car les liens symboliques renvoient tout vers un dossier de package commun.

Mon équipe a rencontré ce problème assez fréquemment lors de la liaison de nos propres bibliothèques internes pendant le développement.

Récemment, nous avons trouvé un outil nommé yalc qui atténue très bien cela et constitue en fait une très bonne boucle de développement. (En tant que tl; dr au lieu de lier l'ensemble du package, il exécute les scripts de pré-publication et copie le résultat dans un dossier lié).

Ce problème semble être continuellement repoussé. Parce que cela perturbe vraiment les flux de travail de tant de gens, pourrions-nous potentiellement avoir une sorte de solution provisoire, comme un `` commentaire de désactivation '' comme suggéré dans # 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$);

Le «commentaire de désactivation» n'est pas beaucoup mieux que de simplement faire des castes de caractères partout, ce qui est assez pénible dans un grand projet. Ci-dessus, j'ai proposé le changement de compilateur suivant:

Si TOUTES ces conditions sont remplies, ne déclarez PAS TS2345 pour les classes avec des membres privés:

  1. Les signatures publiques sont compatibles selon le typage canard TypeScript habituel
  2. Les classes sont définies dans des dossiers de packages NPM avec le même nom et la même version (selon package.json)
  3. Les classes ont le même chemin relatif pour leur module (par exemple "./lib/blah/Bdts")

Si l'un de ces critères n'est pas respecté, vous pouvez signaler TS2345.

Une solution simplifiée serait également toujours meilleure que la situation actuelle, par exemple ne considérer que le # 1, peut-être seulement si les gens opt-in via tsconfig. La mise en œuvre devrait être assez bon marché.

Cette approche a l'avantage de simplement désactiver les fausses alarmes, tout en conservant la sémantique existante. Alors que les hacks de remappage node_modules modifient la résolution du module NPM d'une manière potentiellement incorrecte (par exemple, provoquant un dysfonctionnement du code dans l'exemple hypothétique que j'ai donné ).

Pour être honnête, je ne suis même pas sûr que cela devrait être "corrigé" dans Typescript, car il y a aussi un problème avec le JavaScript brut: L'opérateur instanceof retournera false si la classe de l'objet diffère de la classe fournie.

Ainsi, je préfère attendre avec impatience une meilleure alternative au lien npm qui se connecte peut-être à require (), d'abord.

C'est une bonne idée. Avez-vous regardé pnpm ? C'est un petit pas en avant par rapport à la conception actuelle de node_modules, mais très efficace si je comprends bien.

Il ne s'agit pas seulement de npm link qui peut être remplacé ou non, mais d'avoir plusieurs versions du même package @types/xxx installées en même temps, souvent extraites de dépendances qui fournissent des déclarations TypeScript qui dépendent sur les déclarations standard, comme moi et d' autres personnes l'ont signalé. Le nombre de ces packages augmentera avec l'adoption accrue de TypeScript dans la communauté Node.

@Yogu Je pense que cela confond l'identité et l'égalité. Même si les importations du même package / version à partir de deux emplacements peuvent représenter deux instances différentes d'un type, elles sont toujours de type égal.

Le code (valide) suivant me vient à l'esprit:

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

function foo (bar: a) {}

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

Il en va de même pour les bibliothèques que nous importons.

Les types importés des différentes versions des bibliothèques (et les packages @types ) peuvent être à la fois égaux et différents (si la bibliothèque est mise à jour, la définition de type doit également être mise à jour pour refléter les changements).

Je viens de fusionner un changement qui tentera de détecter les paquets en double en fonction de leur nom et de leur version, et n'en utilisera qu'un. Essayez-le avec typescript@next lors de sa prochaine publication.

Hourra, merci beaucoup d'avoir résolu ce problème! :-)

@pgonzal Merci pour le pointeur vers pnpm, cela semble vraiment intéressant!

@sompylasar Le @types/node est un peu un cas particulier, mais pour @types/react , voici ma suggestion: Mettez toutes les dépendances requises pour l' API d'un module dans le peerDependencies , pas dans dependencies . Cela indique clairement que les versions des dépendances doivent correspondre (ou au moins être compatibles) entre le module parent et le module enfant. Si le parent et l'enfant utilisent tous les deux react mais n'échangent pas d'objets de types react, ce problème ici ne se posera pas en premier lieu.

@harangue Si une classe est déclarée deux fois dans deux fichiers différents, avec le même nom et la même structure, il existe toujours deux classes distinctes qui ne sont pas considérées comme égales par JavaScript. Comme je l'ai mentionné, l'opérateur instanceof distinguera toujours les instances des deux classes.

Voir ce violon pour une démonstration.

C'est la raison pour laquelle je préfère résoudre ce problème au niveau NPM (nous n'avons donc pas plusieurs déclarations en premier lieu si ce n'est pas prévu) que dans TypeScript.

@Yogu : +1: donc si @types/node est un cas particulier, c'est-à-dire que vous ne pouvez pas exécuter un programme utilisant deux versions de nœuds différentes en même temps, ce sera une version, et très probablement celle spécifiée dans le package de niveau supérieur, peut-être que TypeScript devrait le traiter comme un cas spécial, par exemple, utilisez toujours le niveau supérieur @types/node pour chaque dépendance?

@ andy-ms Merci pour cela!

Veuillez l'essayer en utilisant typescript @ next lors de sa prochaine publication.

Je suppose que cela ne s'est pas encore produit. Je l'ai essayé avec quelques projets mais pas de chance pour l'instant. Ce serait formidable de voir une mise à jour dans ce fil dès que next est disponible. @ andy-ms

Il semble que les versions quotidiennes se soient à nouveau arrêtées. Le dernier était: 2.5.0-dev.20170808 .

cc / @DanielRosenwasser

Je ne sais pas si cela est lié, mais en essayant 2.5.1, il semble que je ne vois qu'un seul aspect d'un module, même s'il a étendu d.ts ailleurs.

si j'ai un @types pour quelque chose, disons @types/mongodb et j'ai une déclaration personnalisée qui étend ce module, c'est-à-dire en ajoutant une promisification aux méthodes, donc j'ai maintenant le @types/mongodb qui a le module mongodb et j'ai un fichier d.ts dans mon projet appelé quelque chose comme mongo-promisification.d.ts qui contient un module mongodb .

Donc, avec ce scénario ci-dessus, j'ai un fichier qui a import {somethingFromTypes} from "mongodb" il se plaint que les données du module types ne peuvent pas être trouvées, même si c'est là et valide, mais si j'ai fait import {somethingFromMyExtendingDts} from "mongodb" cela fonctionne bien.

Lors de la compilation, on me dit simplement que le module n'exporte pas ce genre de choses, quand c'est le cas, ce comportement souhaité l'est aussi et j'ai juste besoin de réexporter sur mon d.ts personnalisé ou devrait-il prendre à la fois les types et l'extension d.ts J'ai?

J'exécute la dernière version de test (Windows 10 64 bits) et cela ne semble pas être résolu pour moi.

la reproduction

Structure

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

Courir

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);

Courir

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 Je pense que le problème dans votre situation est que vous avez deux déclarations d'un module, où vous avez besoin d'un module et d'une augmentation.
Vous devriez pouvoir faire mongo-promisification.d.ts comme ceci:

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

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

Sans import , vous êtes dans un contexte ambiant et écrivez une nouvelle déclaration, pas une augmentation.

(Réf manuel )

Peut confirmer que cela fonctionne pour moi maintenant avec [email protected] . Un grand merci à @ andy-ms - cela change la donne!

J'ai eu le même problème, lorsque j'importais Observablevia la bibliothèque Typescript au projet angular-cli et les fonctions utilisaient l'extrait de code

`` `` function getitems (): Observable
http.get (). map (réponse: Réponse) => {
revenirresponse.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 J'aurais besoin d'un exemple complet pour pouvoir reproduire votre erreur. Assurez-vous également que vous utilisez typescript@next - angular-cli peut vous avoir sur une version plus ancienne qui n'a pas la fonctionnalité de déduplication.

J'ai essayé [email protected] mais j'obtiens toujours beaucoup d'erreur TS2300: Identificateur en double.
Malheureusement, je ne peux pas partager l'ensemble du projet. Mais voici quelques détails:
tsconfig du paquet 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"
    ]

tsconfig du projet principal ( @croc/webclient est le package lié):

    "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 pouvez-vous réduire votre projet à un exemple simple qui démontre le problème?

@mhegazy ici c'est
https://github.com/evil-shrike/typescript-npmlink-issue
dans la racine du projet:

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

puis dans main :

npm run tsc

Salut @ evil-shrike, j'ai réduit le problème à:
lib / tsconfig.json

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

main / tsconfig.json

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

On finit donc par inclure les deux (à partir de tsc --listFiles ):

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

Puisque le node_modules vient de include et non de la résolution de module, je ne pense pas que nous appelons realpath dessus, donc il se termine comme deux fichiers inclus différents.
Il est préférable de ne pas inclure vos node_modules toute façon, et de les compiler séparément et de les importer comme vous le feriez pour n'importe quel autre package externe.

@ andy-ms
Ce n'est pas facile à faire. La bibliothèque référencée dans mon cas a beaucoup de d.ts ambiants qui par exemple étend les interfaces globales. Comme JQueryStatic:

interface JQueryStatic {
    cleanData (elems);
}

ou déclarez des préfixes pour chargé (requirejs):

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

Puis quelque part dans la source de lib, il les utilise:

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

Lorsqu'un tel module (de lib) sera importé quelque part dans main, la compilation échouera.

Dans le source de votre bibliothèque, vous devez utiliser les directives /// <reference types="" /> (ou /// <reference path="" /> ) pour vous assurer que les typages nécessaires sont présents chaque fois que votre bibliothèque est importée. De cette façon, il n'aura pas à être dans "inclure"; lors de son importation, les types référencés seront automatiquement ajoutés au projet.

@ andy-ms merci, j'ai refactoré ma lib et maintenant un projet où il npm-link-ed est bien compilé.

Je ne sais pas si ce sont des reproductions trop volumineuses, mais j'obtiens la même chose d'une installation barebones de CLI avec angular @ next et typescript @ next to do with Observable<T> !== Observable<T> :

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

Blue importe et utilise un composant et un service de Red

@intellix Pourriez-vous obtenir un exemple d'erreurs en utilisant uniquement la ligne de commande tsc ? Difficile de dire quelle version de type ng utilise.

@ andy-ms J'ai toujours ce problème. Cela se produit pour moi lorsque je tente d'utiliser le lien npm entre les extensions vscode que je construis. Ils importent tous vscode ce qui provoque des erreurs d'identifiant en double.
TS Version 2.7.0-dev.20171118

Pour moi, cela a fonctionné mapper par exemple "rxjs / *" vers un dossier rxjs spécifique dans node_modules dans la section des chemins du fichier tsconfig.
Maintenant, tout fonctionne bien avec le lien npm.

J'ai également vu cela se produire lors du passage d'un lien symbolique à un lien non symbolique d'un lien de mise à jour de version vers un package.

Voir aussi cette question SO: https://stackoverflow.com/questions/38168581/observablet-is-not-a-class-derived-from-observablet

@dakaraphi @JoshuaKGoldberg Pourriez-vous fournir des instructions pour reproduire ces scénarios?

Avec le nouveau comportement, nous ne devrions pas inclure de package si nous avons déjà vu un autre package avec la même valeur "version" dans son package.json . Si vous avez plusieurs installations avec des versions différentes, vous obtiendrez deux copies différentes du module. Cela pourrait expliquer pourquoi une mise à jour de version briserait cela, si elle n'affectait qu'une des deux installations.

@ andy-ms L'exemple que j'ai sont les référentiels suivants:

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

J'utilise l'installation locale de npm pour référencer vscode-extension-common partir de vscode-extension-fold

Si vous extrayez ces dépôts, ils fonctionnent actuellement car j'ai une solution de contournement de mappage de chemin dans le package.json de vscode-extension-fold . Cependant, si je comprends bien, je ne devrais pas avoir besoin de cette solution de contournement.

@dakaraphi Merci! Il semble que l'erreur soit due au fait que vscode.d.ts est écrit comme une déclaration ambiante globale plutôt que comme un module externe. J'ai créé Microsoft / vscode-extension-vscode # 90.

Cela ne fonctionne toujours pas pour moi lorsque j'essaie de lier 2 packages, chacun ayant une dépendance sur rxjs . J'utilise [email protected] et [email protected] . Les deux packages utilisent exactement la même version. Quelqu'un at-il une solution de contournement pour cela?

@SamVerschueren Pourriez-vous fournir des instructions spécifiques pour reproduire l'erreur? Testez également avec typescript@next .

@ andy-ms je vais voir ce que je peux faire!

@ andy-ms Voici un petit référentiel de reproduction https://github.com/SamVerschueren/ts-link-6496. J'ai utilisé [email protected] pour reproduire cela.

  1. Installez les deux dépendances pour mod-a et mod-b
  2. Compilez mod-b avec yarn build
  3. Compilez mod-a avec yarn build

L'étape 3 échouera avec l'erreur suivante

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.

Toujours en train de rencontrer ce problème avec [email protected]. Également essayé dactylographié @ next et a eu le même problème.

La racine du problème semble être que les packages liés référencent toujours les définitions de type dans leur propre node_modules plutôt que d'utiliser les typages des node_modules auxquels ils sont liés, lorsque cela est possible. Cela combiné avec le fait que:

  1. les globaux ne peuvent pas être redéfinis

    • cela amène le compilateur à se plaindre lorsque le global est défini à la fois dans le node_modules du projet parent ainsi que dans le node_modules dans le package lié

  2. les classes qui sont autrement identiques ne peuvent pas être attribuées les unes aux autres

    • cela amène le compilateur à se plaindre lorsqu'il tente d'assigner une variable dont le type est une classe du node_modules du projet parent à une valeur retournée par le package lié dont le type est défini dans son propre node_modules

J'ai pu contourner ce problème en utilisant la variable de configuration paths . Pour les modules dont les définitions proviennent de @types/* , comme suggéré ici , vous pouvez simplement utiliser:

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

Dans le cas où vous rencontrez ce problème avec un package fourni avec des définitions de type qui définissent des classes ou des globaux, vous devez les ajouter manuellement. Par exemple, rxjs :

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

Je rencontre également des problèmes avec les liens symboliques lorsque j'ajoute un package local, en utilisant TS 2.8.3:

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

Depuis la v3, npm les installe apparemment avec des liens symboliques au lieu de copier les fichiers.

Cependant, lorsque j'essaie de compiler, le compilateur voit le fichier de définition lié comme deux fichiers séparés et en conflit:

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'.

Si je copie manuellement les fichiers à la place, cela fonctionne comme prévu. Je peux contourner ce problème en définissant typeRoots: ["./node_modules/**/"]

Cette page vous a été utile?
0 / 5 - 0 notes