Typescript: Declaraciones de tipo duplicado con enlace npm

Creado en 15 ene. 2016  ·  147Comentarios  ·  Fuente: microsoft/TypeScript

Usando TypeScript 1.7.3.

Supongamos que tengo los siguientes paquetes npm.
Los archivos de declaración son generados por el compilador TypeScript, y se hace referencia a ellos desde los otros paquetes por medio de la forma descrita aquí .

paquete-a

ts src:

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

declaración ts:

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

paquete-b (depende del paquete-a):

ts src:

import ClassA from 'package-a';

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

declaración ts:

import ClassA from 'package-a';

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

paquete-c (depende de paquete-a y paquete-b):

ts src:

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

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

La última línea provoca un error durante la compilación:

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

Cuando elimino la línea private foo; de la declaración del paquete-a, TypeScript no emite ningún error.
Sin embargo, esta solución es un poco dolorosa.

Entiendo que exponer propiedades privadas a la declaración es por diseño (https://github.com/Microsoft/TypeScript/issues/1532).
Creo que TypeScript debería ignorar las propiedades privadas al compilar la asignación de variables.
¿O hay alguna solución mejor para esto?

@types Bug Fixed

Comentario más útil

Acabo de fusionar un cambio que intentará detectar paquetes duplicados según su nombre y versión, y usará solo uno. Pruébelo usando typescript@next la próxima vez que se publique.

Todos 147 comentarios

Solo hay una declaración raíz de ClassA aquí, por lo que este error no debería ocurrir.

Bueno, lo siento, encontré que esto está relacionado con npm link .

Cuando utilizo npm link , los paquetes se instalan como se muestra a continuación, ya que simplemente crea enlaces simbólicos.

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

Como se muestra, parece que hay dos archivos de declaración diferentes para el paquete-a.
Si instalo paquetes normalmente usando npm install , esto no sucede porque la declaración del paquete-a no está incluida en el paquete-b en este caso.

Espero que haya alguna solución para esto de todos modos, pero podría ser difícil y de baja prioridad.

Terminé sin usar npm link , y esto ya no me importa.

Bastante justo, pero alguien más podría: guiño:

en realidad, hay dos archivos en el disco con dos declaraciones de ClassA. entonces el error es correcto. pero debemos considerar los módulos de nodo cuando comparamos estos tipos. Este problema se ha informado anteriormente en https://github.com/Microsoft/TypeScript/issues/4800 , para Enums cambiamos la regla a una verificación semi-nominal. posiblemente haga lo mismo para las clases.

+1 en esto con TS 1.7.5 con todos los paquetes relevantes vinculados a NPM. Traté de construir un caso de prueba que exhiba el problema, pero no pude. No importa lo que intenté, TS estuvo bien con el escenario que veo fallar con TS2345 en mi aplicación, y por lo que pude ver, todas las copias del archivo .d.ts problemático eran enlaces simbólicos al mismo archivo, por lo que no debería han sido declaraciones diferentes dentro del tipo. Sin embargo, sería bueno si el error emitido por Typecript hiciera referencia a los archivos que declararon los dos tipos incompatibles, ya que eso podría arrojar luz sobre algo que no estoy considerando. En este momento dice que hay dos definiciones, pero no hace nada para ayudar al desarrollador a identificar el problema.

Como solución alternativa, puede usar <any> en la expresión en conflicto para omitir la verificación de tipo. Obviamente, esto podría requerir que hagas otro tipo de anotación donde no debiste haber hecho antes. Espero que alguien pueda aislar este problema en algún momento.

EDITAR: dejó en claro que el enlace NPM está en juego en mi caso

Noticed TS 1.8 está disponible, actualizado y el problema también existe en esa versión.

Gracias por todo el trabajo de análisis y documentación de este problema. Tenemos el mismo problema en algunas de nuestras bases de código. Portamos algunos proyectos para usar correctamente las dependencias package.json pero ahora vemos esto cuando usamos npm link durante el desarrollo.

¿Puedo ayudar en algo para resolver este problema?

Estoy usando Lerna que vincula paquetes simbólicos y veo el problema allí también. Typecript versión 2.0.3.

Desafortunadamente, Lerna y sus enlaces simbólicos son un requisito estricto, por lo que utilicé esta desagradable solución para lograr que esto se compilara bien y que los consumidores pudieran verificar correctamente el tipo:

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

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

La clase es muy pequeña, por lo que no fue tan arduo, y no espero que cambie realmente nunca, por lo que considero que esta es una solución aceptable.

FYI, también terminé aquí como resultado de usar npm link y obtener este error. ¿Alguien ha encontrado una solución para esto?

@xogeny, ¿ puede explicar cómo el enlace npm le está causando este problema?

@mhegazy Bueno, comencé a recibir estos errores como el anterior (excepto que estaba usando Observable de rxjs , es decir, "El tipo 'Observable' no se puede asignar al tipo 'Observable'). Esto, por supuesto, parecía extraño porque los dos a los que hacía referencia Observable eran exactamente la misma versión de rxjs en ambos módulos. Pero cuando los tipos "se encontraron", me salió un error. Investigué y eventualmente encontré este problema donde @kimamula señaló que si usa npm link , obtendrá este error. Yo, como otros, solucioné esto (en mi caso, creé una interfaz duplicada solo de la funcionalidad que necesario en un módulo, en lugar de referencias rxjs ).

Eso responde tu pregunta? Lo pregunto porque no creo que mi caso parezca diferente a los demás aquí, así que no estoy seguro de si esto le ayuda.

Hemos trabajado en TS2.0 específicamente para habilitar escenarios npm link (consulte https://github.com/Microsoft/TypeScript/pull/8486 y # 8346). ¿Tiene una muestra en la que pueda ver dónde el enlace npm todavía no funciona para usted?

¿Eh? Estoy ejecutando 2.0.3 (lo comprobé). Intentaré crear un caso reproducible.

Por cierto, debe hacer un seguimiento de estos hilos, ya que implican que esto sigue siendo un problema a partir de TS 2.0:

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

El problema que veo en mi repositorio de Lerna está algo complicado, así que hice una versión simplificada en https://github.com/TypeStrong/ts-loader/issues/324 allí también.

Estoy usando mecanografiado 2.0.3 y veo este error con Observable como se describe anteriormente, por ejemplo

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

También estoy agregando esto en un paquete de Lerna monorepo. Parece que la mayoría, pero no todas las partes del sistema de tipos, utilizan la ruta real para identificar archivos de forma única. Si viaja por la rama que usa la ruta del enlace simbólico en lugar de la ruta real, terminará con tipos idénticos pero diferentes.

Este es un problema bastante brutal que solo afectará a bases de código más complejas, y parece imposible solucionarlo sin tomar medidas drásticas, así que espero poder convencerlos a todos de que le presten la atención que se merece. 😄

Es más notorio en los casos en los que tiene una aplicación que depende de la Dependencia A, la Dependencia A depende de la Dependencia B y vende objetos que contienen tipos de la Dependencia B. La aplicación y la Dependencia A npm link Dependencia B y esperan ser capaz de importar tipos de él y hacer que describan lo mismo.

Esto da como resultado mensajes de error profundos, y estoy a punto de revisar y eliminar todas las propiedades private y protected en mis bibliotecas porque ya he perdido mucho tiempo con esto. :

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 aprecio que todos hayan investigado esto; ¡gracias!

@tomdale, ¿estás usando Webpack, tsc u otra herramienta de construcción? Mi problema parece ocurrir solo cuando se compila a través de Webpack (consulte el repositorio vinculado de mi comentario anterior ).

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

Así es, está usando ts-node (para la aplicación raíz). Las dependencias, sin embargo, son paquetes compilados con tsc .

Me acabo de encontrar con este problema y es un problema importante para nosotros porque intentamos dividir nuestro back-end en muchas bibliotecas pequeñas. Durante el desarrollo, a menudo necesitamos vincular npm nuestros repositorios. El problema específico que encontré y que me impulsó a encontrar esto es el 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({});
    }
}

Esto funciona si no npm link , pero cuando lo hago, obtengo:

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 única sugerencia que puedo hacer es evitar private . Ya no publico ningún paquete con private debido a este problema y solo uso los prefijos _ estilo JavaScript en su lugar. Me encuentro con https://github.com/Microsoft/TypeScript/issues/7755, que es una discusión similar sobre por qué private entra en un sistema de tipo nominal en lugar de estructural y, por lo tanto, lo he prohibido en mi propios proyectos porque es demasiado fácil terminar con diferencias de versión (por ejemplo, NPM 2 o usar npm link ).

@blakeembrey cuando dices evitar privado, ¿sugieres que puedo cambiar algo en mi código? Supongo que la definición de tipo observable es el problema, ¿no?

@jeffwhelpley Sí, lo siento, no tienes la culpa. Es Observable . Desafortunadamente, el consejo de evitar private es muy delgado y no se aplica por completo a usted 😄 Tal vez pueda plantear un problema, supongo, rxjs sobre el uso de private en sus interfaces públicas?

Editar: principalmente comenté porque había seguido el problema antes y evité unirme con mis propias experiencias, pero pensé que también podría escribir mis pensamientos nuevamente, en su lugar, son similares a https://github.com/Microsoft/TypeScript/issues/ 6496 # issuecomment -255232592 (donde @tomdale sugiere eliminar private y protected , hice lo mismo hace un tiempo).

Tuve la impresión de @mhegazy de que sentía que no había ningún problema con npm link . Pero todavía parece estar atormentándonos a nosotros y a otros. ¿Entonces no estoy seguro de dónde se encuentra este problema? ¿Es un problema reconocido con TS 2.0+ o simplemente me falta una solución alternativa en alguna parte?

Tengo el mismo problema y no parece ser causado por npm link . Todavía lo obtengo si lo instalo usando npm install file.tar.gz . Aquí está el error:

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

Así es como se ve mi 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);
  }

Se queja de la línea this.user$ . Stormpath tiene user$ definido de la siguiente manera:

@Injectable()
export class Stormpath {

  user$: Observable<Account | boolean>;

@xogeny Odd, entendí que la identidad de la definición estaba ligada a la ubicación del archivo, lo que significaría que siempre causarían problemas al usar npm link (porque la dependencia npm link ed tendría sus propias dependencias instaladas) . Quizás se haya cambiado la identidad de la definición; el uso de hashes de archivo podría ser una buena solución en TypeScript. Desafortunadamente, solo hay una docena de formas diferentes de terminar con módulos duplicados en JavaScript ( npm install de GitHub, npm install , clones manuales, los conflictos de versiones pueden incluso resultar en que la misma versión aterrice en diferentes ubicaciones debido a cómo funciona el algoritmo de resolución del módulo del nodo, etc.).

@blakeembrey Quizás. Pero entonces, ¿de qué se trataba esto ?

Tenga en cuenta que no me quejo. Solo estoy tratando de averiguar si hay alguna esperanza de que esto se resuelva o no. Es una espina grave en nuestro costado por todas las razones que mencionó @jeffwhelpley .

@xogeny Lo sé, también lo estoy intentando, me encantaría verlo resuelto correctamente 😄 Leí los problemas vinculados, pero todos están diseñados para resolver la ruta real de un enlace simbólico, lo que implica si tiene dos archivos (reales) seguirán en conflicto porque se resolverán en diferentes ubicaciones. Que es lo que sucede cuando npm link de un proyecto a otro ya que ambos tendrían sus propias dependencias que pueden diferir con los símbolos reexportados del paquete npm link ed.

Editar: puedo confirmar, todos los problemas se deben a dos archivos. npm link lo activaría porque es simple tener una dependencia en un repositorio que acaba de vincular que es la misma dependencia que en el proyecto al que se vinculó. Una reproducción simple sería hacer un npm install de la misma dependencia en dos niveles diferentes de una aplicación y observarlos errores.

image

Para cualquiera que siga este hilo ... Probé la solución que se describe aquí y parece funcionar (hasta ahora).

He reproducido este error.

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

Dado que hay dos instalaciones de rxjs , obtenemos:

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

Tengo una solución que funciona muy bien para la línea de comandos, pero Visual Studio aún se estropea todo: https://github.com/Microsoft/TypeScript/issues/11107#issuecomment -254003380

mi nueva solución para Windows + Visual Studio 2015 es copiar automáticamente mi xlib Library src y dist carpeta en las carpetas node_modules\xlib\src y node_modules\xlib\dist del proyecto consumidor.

aquí está la parte importante de mi script de archivo por lotes robocopy si alguien lo quiere:

: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

Perdón por volver a molestarme con este problema, pero es un serio lastre para nuestro proyecto no poder hacer npm link mientras hacemos cambios. Me encantaría ayudar con un PR si uno de los colaboradores actuales de TypeScript pudiera darme una pequeña guía sobre dónde comenzar a buscar en la base de código.

También estoy luchando con este. Hemos adoptado TS a partir de una pequeña aplicación, ahora lo hemos dividido en submódulos y los hemos vinculado y… BOOM. TS ya no compilará. ¿Sigue siendo un problema en todas las etiquetas dist de TS? Actualmente estoy experimentando esto en @rc (2.1.1).

@heruan y @jeffwhelpley, ¿ puedes typescript@next Hemos solucionado algunos problemas relacionados. y si sigue viendo el problema, proporcione más información sobre la configuración de su proyecto.

@mhegazy Estoy en Version 2.2.0-dev.20161129 y todavía tengo el problema. El problema específico es que tengo un proyecto (llamémoslo ProjectA) que contiene una "interfaz" (usando una clase, pero así puedo usar la clase como token para Angular 2 DI) de la siguiente manera:

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

Luego, en un proyecto completamente separado (llamémoslo ProjectB) que tiene una clase que implementa la interfaz del primer proyecto de esta manera:

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
}

Cuando hago una compilación normal de mecanografiado para ProjectB, funciona bien. Pero si npm link ProjectA desde el directorio raíz de ProjectB y luego ejecuto tsc nuevo, obtengo:

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

No pude replicar en un proyecto simulado, supongo que me falta la causa del problema, por lo que no puedo replicarlo. @jeffwhelpley ¿puedes publicar un proyecto simulado que reproduzca el problema? Creo que un proyecto de Lerna debería estar bien y ser fácilmente comprobable.

@heruan Intentaré configurar eso.

Uno, para tu información, sin embargo. Creo que puedo haber encontrado una solución. El problema se resuelve si npm link rxjs en ProjectA y ProjectB. Esto tiene sentido porque en ese caso, tanto ProjectA como ProjectB están usando exactamente los mismos archivos rxjs. Sin eso, técnicamente están usando diferentes archivos (aunque la misma versión):

Si solo npm link ProjectA de ProjectB, entonces:

  • ProjectB apunta a node_modules / rxjs
  • ProjectA existe como un enlace simbólico en node_modules / ProjectA y el rxjs al que hace referencia está en node_modules / ProjectA / node_modules / rxjs

Pero si npm link rxjs en ambos, ambas referencias rxjs se vincularán simbólicamente a la misma ubicación npm exactamente global.

De todos modos, esto obviamente todavía no es lo ideal, pero al menos algo que puede hacernos avanzar.

Además ... no estoy seguro de si esto es relevante o importante (lo veré una vez que configure el proyecto de prueba), pero mis dos bibliotecas (es decir, ProjectA y ProjectB) son en realidad repositorios npm privados.

Gracias @jeffwhelpley por la pista, pero como estoy usando Lerna, todos los módulos ya están vinculados entre sí, por lo que leen el mismo archivo, pero creo que el compilador de TS está teniendo en cuenta la ruta del enlace y no la real. Puede que me equivoque, ya que no puedo reproducir en un proyecto simulado, y realmente me estoy volviendo loco ...

¿Alguien aquí puede resolver esto de una manera elegante?

Además, tenga en cuenta que esto no es solo un problema con npm link , también obtendrá este problema en las compilaciones de producción, cuando sus dependencias compartidas apuntan a una versión diferente.

es decir. ProjectA necesita [email protected] y ProjectB usa [email protected]

Cuando instale ProjectA como una dependencia en ProjectB, también tendrá tipos duplicados, ya que habrá, por ejemplo, dos declaraciones Observable , una en node_modules/rxjs y una en node_modules/project_a/node_modules/rxjs

Puede evitar esto permitiendo que la versión rxjs en ProjectA sea algo así como ~4.9.0 , de modo que npm install no necesite descargar su propia versión y, en su lugar, utilizará la versión ProjectB. Pero tenga en cuenta que esto no es solo un problema de flujo de trabajo de desarrollo.

Publicando aquí según la sugerencia de @ andy-ms. Lo intenté de nuevo ayer con la última versión 2.0.xy todavía lo tenía.

Recibo esto con las mecanografías para Angular 1: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/10082#issuecomment -253023107

Me encontré con esto nuevamente hoy, específicamente el problema con los enlaces simbólicos. Mi configuración es algo como esto:

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

Si solo tengo @types/angular , tsc funciona bien. Si tengo toda la suite ( @types/angular-{animate,cookies,mocks,resource,route,sanitize} ), empiezo a recibir muchos errores 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'.

Lo arreglé agregando la base ../../node_modules/@types como typeRoots a mi tsconfig.json :

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

Intenté agregar el node_modules/@types local, pero no funcionó.

@heruan Un truco que comencé a hacer es implementar mi propio script npm para vincular / desvincular en lugar de usar la funcionalidad de lerna. Entonces, podría hacer algo como lerna run link y luego en todos sus archivos package.json tiene un script npm llamado link que hace todos los enlaces npm, incluido (en mi caso) npm link rxjs . Parece funcionar bien, no definitivamente no es ideal.

@jeffwhelpley, ¿puedes compartir tu solución aquí?

@yvoronen No puedo compartir todo mi código, pero mi solución se describe arriba. En un nivel alto, la clave que he encontrado es asegurarme de vincular npm no solo todos los proyectos locales en los que está trabajando, sino también vincular npm las bibliotecas externas que pueden estar causando el problema (en mi caso, rxjs es el problema debido a vars privadas en el objeto Observable). Entonces, uso lerna para administrar todos mis proyectos locales y luego ejecuto lerna run link . Debajo de las escenas, esto llama a npm run link dentro de cada una de las carpetas raíz de mi proyecto. Entonces, necesita tener el script link definido en su package.json de esta manera:

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

Espero que tenga sentido, pero avíseme si tiene alguna pregunta.

Quería proporcionar una actualización. De un intercambio casual que tuve con @mhegazy , esto es lo que estamos pensando.

  • Una solución que estamos considerando es el concepto de distinguir paquetes según su versión y el nombre de su resolución. No tengo todos los detalles de lo que implicaría esto.
  • Otra es simplemente expandir completamente la ruta para obtener la identidad "verdadera" de un enlace simbólico. Creo que esto es más simple, pero más limitado cuando se trata de tratar con el mismo paquete en diferentes versiones, pero ayuda a resolver una cantidad decente de casos.

¿Está seguro de que su comentario pertenece a este número? Suena completamente
diferente.

El jueves 12 de enero de 2017 a las 3:14 a.m. Nikos [email protected] escribió:

Tenga en cuenta que no estoy usando tipos o enlace npm AFAIK.

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

-
Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment-272137732 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AAUAmcMXodOvU7coymMqGzTofD4pMagpks5rRgsogaJpZM4HFcWl
.

@dobesv es en realidad la razón por la que ve el problema en primer lugar. TypeScript reconoce la declaración de clase como dos declaraciones separadas porque no podía distinguir la ruta de enlace simbólica de la ruta verdadera. La solución es

  1. Expanda el enlace simbólico.
  2. Compruebe si el paquete que lo contiene es el mismo.

@DanielRosenwasser Lo siento, mi comentario fue una respuesta al comentario de otra persona "El jueves, 12 de enero de 2017, 3:14 a. M. Nikos @ . * > Escribió" ... quién es y lo que dijeron. Ya no recuerdo, creo que preguntaban sobre algún problema en este hilo de comentarios, que no tenía nada que ver con el enlace npm.

Pero mientras estoy aquí, debo mencionar que hay algo gracioso en la forma en que el nombre de archivo juega un papel en los tipos. Hoy tuve un problema con RxJS en el que se quejaba de que tal método no estaba definido en Observable. La razón fue que la biblioteca HTTP tenía su propia copia privada de rxjs que era diferente a todos los demás. De hecho, encontré cuatro copias diferentes de rxjs en mi árbol node_modules.

Este parece ser un enfoque problemático que seguirá siendo problemático y confuso.

Si todo este concepto del nombre de archivo que de alguna manera juega un papel en la identidad de un tipo desapareciera, creo que este problema del enlace npm también desaparecería.

Todavía estoy un poco confuso sobre cómo funcionaría eso ... Soy nuevo en TypeScript. Pero esa es la impresión que tengo, es que esta cosa de "el nombre de archivo importa" me ha causado bastante confusión en relación con las bibliotecas que estoy usando (ionic2 y angular2 y rxjs).

Bueno, el problema es que el nombre del archivo sigue siendo la identidad de un módulo en Javascript, por lo que no puede desaparecer por completo. ¿Alguien puede explicar cuáles son los problemas con el uso de la ruta canónica (resolución del enlace simbólico) con respecto a múltiples versiones de paquetes? Si hay varias versiones de paquetes dentro de un árbol, tendrán múltiples rutas canónicas absolutas, ¿verdad?

EDITAR: Me di cuenta de esto después de publicar, y este comentario lo resume bien:
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -257016094

exclude y compilerOptions.typeRoots son completamente ignorados por tsc. Probé todas las combinaciones para ignorar las rutas de enlace simbólico, pero simplemente no lo hará.
está viendo el módulo como una ruta completamente diferente, como si estuviera resolviendo el enlace simbólico y no entendiera los patrones excluidos.

por ejemplo, tengo G:\www\cim-service-locator npm vinculado con npm link cim-service-locator . en la ruta de mi proyecto en G:\www\cim-backend , los errores se muestran así:

crop

Intenté todas las combinaciones posibles de excludes / includes / typesRoot pero no pude hacer que tsc los ignorara. usando 2.2-dev.20170131

Encontramos este problema usando "npm link" (a través de un problema SPFx informado por @waldekmastykarz) y también sin "npm link" (ver error # 11436).

Finalmente me di cuenta de que el rigor del compilador de TypeScript se debe a incompatibilidades que pueden ocurrir de manera realista debido al extraño diseño de la carpeta node_modules . Considere este ejemplo:

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]

En este ejemplo, B @ 2 tiene que ser instalado en subcarpetas para evitar un conflicto con la dependencia A 's en B @ 1 . Ahora, suponga que ClassB se extiende desde ClassE, y tenemos algo como esto:

B / paquete.json

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

Si package.json de C solicita [email protected] , entonces las dos copias de ClassB pueden terminar con diferentes implementaciones de clase base, lo que significa que en realidad son incompatibles. El código puede fallar en tiempo de ejecución si intenta usarlos indistintamente.

En este ejemplo, TS2345 evitaría ese error, lo cual es bueno. Sin embargo, NO es esencial: si el compilador tratara las dos copias ClassB como equivalentes, su sistema de tipos aún sería internamente consistente y tendría un comportamiento determinista.

Esto es importante porque para nosotros TS2345 produce principalmente falsas alarmas. Estas falsas alarmas obligan a las personas a escribir "como cualquiera" siempre que compartan tipos entre paquetes de NPM, lo que provoca otros errores. Entonces, el rigor está creando más problemas de los que resuelve.

Me gustaría proponer la siguiente solución:

Si TODAS estas condiciones son verdaderas, NO informe TS2345 para clases con miembros privados:

  1. Las firmas públicas son compatibles de acuerdo con la tipificación de pato de TypeScript habitual
  2. Las clases se definen en carpetas de paquetes NPM con el mismo nombre y versión (según package.json)
  3. Las clases tienen la misma ruta relativa para su módulo (por ejemplo, "./lib/blah/Bdts")

Si no se cumple alguno de estos criterios, está bien informar TS2345.

@iclanton @ nickpape-msft

El error de

Hola chicos,
¿Alguien encontró una solución?
Tengo el mismo problema cuando vinculo un proyecto con otro con RxJS.
Gracias ;)

Hola, una solución temporal es envolver los Observables devueltos por una dependencia con Observable#from .

Aún no hay solución. ?

Parece haber dos problemas aquí.

Los usuarios de ts-loader obtienen errores erróneos por definiciones duplicadas, parece ser causado por una entrada no válida en la API del compilador. Una solución para eso está disponible en TypeStrong / ts-loader # 468.

El otro problema es si tiene el mismo paquete (mismo paquete npm + versión) instalado dos veces localmente en el sistema de archivos (sin usar npm link ) en dos carpetas anidadas, con Enums o clases con miembros privados, comparando el los tipos de estos dos paquetes fallarían por ser incompatibles.
Este problema es un poco más complicado y requerirá trabajo adicional para que el compilador "deduplica" los paquetes antes de procesarlos.

Si ninguna de estas dos categorías se aplica a su caso, presente un nuevo problema y bríndenos información suficiente para reproducir el problema localmente, y estaremos encantados de investigar más a fondo.

Una solución alternativa conocida es utilizar una solución multiproyecto que eliminará las carpetas duplicadas, es decir, asegurando que ambas subcarpetas node_modules terminen enlazadas simbólicamente al mismo destino.

Rush (que usamos) y Lerna son ejemplos.

@smcatala Puede explicar su solución. Necesito arreglarlo urgentemente. Gracias.

@ leovo2708
módulo 'foo':

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

código de cliente en otro módulo, que depende del módulo 'foo':

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

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

@ leovo2708 la solución simple es no usar npm link .

usando ts 2.1, he podido usar el enlace npm con una sola biblioteca (llamémoslo xlib , que es mi ejemplo real) pero deberá asegurarse de que los módulos que su biblioteca ( xlib ) cargas no se duplican en la carpeta node_modules del proyecto consumidor.

Hago esto mediante el siguiente flujo de trabajo

  1. eliminar node_modules
  2. npm link xlib que crea el sym_link a xlib en el node_modules mi proyecto consumidor
  3. npm install que instala el resto de las dependencias de mi proyecto de consumo

Realmente no he estado siguiendo esta conversación ni he comprobado si este problema ha cambiado / modificado desde 2.2, pero aunque compartiría mi solución para ts 2.1

En caso de que sea útil, reuní una reproducción mínima de las múltiples definiciones del caso de enumeraciones aquí: https://github.com/rictic/repro-npm-link-typescript-issue

@mhegazy Vemos el problema anterior cuando usamos el enlace npm, aunque no creo que eso afecte al resto de su análisis.

Muchas gracias, espero que se solucione pronto. Sin embargo, utilicé una nueva solución, dupliqué cualquier archivo usando Observable. No es bueno, sino solo una solución temporal.

tsconfig.json expone un mapeo de ruta, agrega dependencias duplicadas en paths , por lo que se cargará desde el node_modules correcto en lugar de uno 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"]
    }
  }
}

No estoy seguro si ya se mencionó aquí, pero esta solución funcionó para mí: https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001

Es básicamente lo mismo que la solución de @charpeni anterior, excepto sin el prefijo "../" en las rutas. (lo que parece extraño, ya que ¿no significaría eso que el archivo tsconfig.json estaría en una subcarpeta de la raíz del proyecto?)

Esa es una gran idea @charpeni. He utilizado esa configuración de rutas para solucionar otros problemas similares, pero también parece ideal para este. De hecho, me pregunto si la configuración correcta de paths en el proyecto consumidor (en lugar de en cada proyecto consumido) podría distraer al compilador de TypeScript de la siguiente resolución de nodo. Si eso funciona, sería un truco O (1) en lugar de un truco O (n). Básicamente, tal esquema ejecutaría la resolución de nodos de forma estática y luego rellenaría los resultados en tsconfig.

Estoy experimentando con estas cosas de forma semipública si alguien quiere ver (o ayudar ...). Probablemente intentaré la idea anterior a continuación.

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

Para un uso más fácil, también puede establecer las rutas de esta manera:

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

El enlace npm es una parte crucial del flujo de trabajo cuando se trabaja con varios paquetes en lugar de una arquitectura de repositorio único. TS debería poder ver que los dos paquetes son idénticos y no errores

@charpeni No pude conseguir que la solución funcionara. Para que quede claro, ¿a qué tsconfig.json se debe agregar esto? ¿El paquete raíz o el paquete vinculado?

También estoy experimentando este problema. De repente comenzó a suceder el lunes y no estoy seguro de por qué. Esto realmente obstaculiza el desarrollo, especialmente cuando se trata de desarrollar paquetes para nuestros proyectos. Probé varias soluciones para solucionar este problema. Ejecutar mklink /j en Windows aún causa este problema, por lo que no es un problema de enlace npm. Si alguien tiene una solución alternativa o una solución, esto sería de gran ayuda.

Mi solución es vincular npm cada paquete "duplicado" tanto en el paquete raíz como en la dependencia, porque luego se refieren a los mismos archivos nuevamente.

Por cierto, este problema no tiene nada que ver con @types

Terminamos usando el patrón glob.

@felixfbecker Para la implementación, está disponible aquí: https://github.com/sherweb/ng2-materialize/blob/master/demo-app/tsconfig.json#L19 -L22

Tengo un problema similar, excepto que está completamente relacionado con @ types / node.

libA depende de @ nodo / tipos
libB depende de libA y @ node / types
libC depende de libA, libB y @ node / types

libA se construye bien.
libB npm vinculado al archivo de compilaciones libA.
libC npm vinculado a libA y libB falla la verificación de tipos con errores 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'.

Intenté jugar con "tipos" y "typeRoots" sin suerte.

@charpeni Parece que su proyecto también depende de @ types / node. ¿Tiene alguna idea de la solución a mi problema o una solución alternativa?

@nicksnyder, eso podría deberse a que son versiones diferentes, y @types/node es una declaración global, lo que significa que no puede definir los mismos nombres dos veces. Esta es la razón por la que es mejor que los paquetes _no_ dependan de las tipificaciones ambientales, estas deben ser proporcionadas por el usuario:
https://github.com/Microsoft/types-publisher/issues/107

@nicksnyder Tuve un problema similar y pude solucionarlo mediante npm vinculando los tres proyectos a una sola instalación de @ tipos / nodo. Dado que las definiciones se definen en el mismo archivo, ya no son duplicados.

@felixfbecker Verifiqué que todos los proyectos dependen de la misma versión de node.

FWIW libA es https://github.com/Microsoft/vscode-languageserver-node/tree/master/jsonrpc , libB es https://github.com/Microsoft/vscode-languageserver-node/tree/master/client y libC es mi propia extensión VS Code.

@uncleramsay ¿cómo exactamente npm link @types/node ?

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

Me gustaría hacer la solución de vinculación, pero también he pirateado esto eliminando la dependencia @ types / node en libA y libB, y agregué un refs.d.ts que contiene referencias locales a la copia de node de libC.

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

Descubrí que podía resolver los problemas que tenía de la descripción en el comentario en https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -225303098

solo agregamos soporte para la resolución de enlaces simbólicos para módulos ...

En lugares separados en la base de código cuando usábamos dos estilos de referencia diferentes:

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

Estos dos son incompatibles en el caso de que los módulos node_modules estén vinculados simbólicamente, ya que la resolución del módulo (con types= ) se expande a la ruta real, pero path= no. Esto da como resultado dos archivos diferentes referenciados al compilar con tsc --listFiles , el enlace simbólico y la ruta real.

La solución con la que nos decidimos fue utilizar uno u otro, pero nunca ambos. También ayudó a especificar typeRoots: [] en tsconfig para evitar que el compilador cargue automáticamente los tipos de node_modules/@types en el caso de usar el estilo reference path= .

Creo que la preferencia en el futuro (al menos para nosotros) es preferir el estilo types= .

Idealmente, sin embargo, sería preferible expandirse a la ruta real en reference path= y verificar si hay rutas coincidentes duplicadas para evitar tales problemas.

Espero que ayude a alguien.

@nicksnyder deberías poder hacer algo como esto:

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

De esa forma, B y C apuntan exactamente a los mismos archivos que A.

@uncleramsay tenga en cuenta que entonces son todas las mismas versiones, que puede que no hayan sido antes

¿No pueden las dependencias entre pares ser una solución para esto?
http://codetunnel.io/you-can-finally-npm-link-packages-that-contain-peer-dependencies/

Las dependencias entre pares se inventaron para una situación en la que un complemento quiere decir con qué va. En cierto modo funcionan bien para ese caso. Pero causan muchos problemas si las personas comienzan a convertir todas sus dependencias en dependencias de pares, con la esperanza de evitar la duplicación de "npm install".

Pasamos meses desterrándolos de nuestros repositorios de git internos. Cuando se usa como creo que está sugiriendo, las dependencias entre pares le permiten resolver un problema de versiones en paralelo intercambiándolo por varios problemas nuevos:

  • todo el árbol está invertido, es decir, cada paquete ahora se hace responsable de asumir una dependencia estricta de los paquetes que solían ser dependencias indirectas, en muchos casos sin tener idea de para qué sirve

  • si se elimina una dependencia entre pares, estas dependencias duras probablemente nunca se eliminarán

  • los autores de paquetes se ven tentados a utilizar rangos amplios para sus patrones de versión de pares, afirmando que trabajan con versiones con las que nunca han probado; las construcciones rotas de repente se convierten en un problema del consumidor

Bien dicho.

soluciones alternativas

Aquí hay 3 opciones para las soluciones que utilicé:

opción 1: use vscode no visual studio

El compilador tsc es mucho más indulgente que VS2017, probablemente porque VS2017 rastrea el código (incluido el enlace simbólico node_modules ) para proporcionar un buen intellisense y, por lo tanto, se confunde. Sin embargo, tengo grandes proyectos complejos de módulos múltiples npm, así que use VS2017 ... así que lea las opciones 2 y 3 si tiene necesidades similares ...

opción 2: emitir d.ts

si usa outDir y rootDir (en su tsconfig.json ) su módulo lib enlazado simbólicamente debe emitir declaraciones d.ts y esas declaraciones deben estar en el módulo lib package.json types propiedad.

aquí hay un ejemplo de cómo debería verse el tsconfig.json de su módulo lib

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

y el package.json su módulo lib debe incluir algo como lo siguiente:

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

Esta opción funciona bien, el principal problema es que en Visual Studio, al depurar o "ir a la definición" o "mostrar todas las referencias", le mostrará los d.ts no los archivos fuente mecanografiados, lo que anula el beneficio principal de Visual Studio (navegación en grandes proyectos)

si desea ver un ejemplo real de esto en la naturaleza, mire el módulo npm xlib v8.5.x

opción 3: emitir .js línea con la fuente (mi opción favorita)

¡Puede usar sus archivos .ts directamente para escribir módulos lib enlazados simbólicamente! pero solo si no usa el archivo outDir`` and rootDir in your tsconfig.json```. Eso permitirá que la referencia de VS2017 funcione correctamente. Aquí están los ajustes de configuración que necesita:

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

y el package.json su módulo lib debe cambiarse a:

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

advertencias (cosas que no funcionarán con la opción 3)

Las soluciones anteriores solo funcionan si cada módulo lib NO emite información de tipo redundante. Por ejemplo, solía hacer que mi biblioteca xlib exponga las definiciones de tipo @types/async . Pero luego tenía otra biblioteca que también hacía referencia de forma independiente a @types/async . El uso de los archivos .ts directamente para escribir hace que tsc importe async de dos módulos lib, lo que provoca que emite varios tipos de problemas de duplicate identifier . para resolver esto, necesita no importar el mismo @types de varios módulos lib, o usar la opción 2 .d.ts solución alternativa

resumen

Espero que esto pueda ahorrarle las horas que me tomó ... En general, esto es extremadamente doloroso y espero que el equipo de mecanografiado pueda arreglar los módulos enlazados simbólicamente. Pero al menos funciona ahora (antes de 2.x era básicamente imposible)

La solución alternativa publicada por @mhegazy en https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001 (una variación de la solución alternativa 2 @jasonswearingen) nos resolvió esto cuando usamos módulos vinculados en un proyecto de lerna.

Solo pensé en compartir mi experiencia ... tratando de crear / extraer una biblioteca de un proyecto existente para que la biblioteca se pueda compartir con otros proyectos.

Windows 10 Enterprise
VS 2015 Actualización 3
Herramientas para VS2015 2.2.2
VS Code 1.12.2
Texto mecanografiado 2.2.2
NPM: 3.10.9
Nodo: 6.9.2

Tenemos un proyecto VS 2015 ASP.MVC con una interfaz Angular 4.1.x del que comenzamos a extraer algunos componentes para crear una biblioteca común para que puedan usarse en otros proyectos.

El proyecto de la biblioteca se construye usando VS Code y usa rollup para construir versiones es2015, es5 y umd en la carpeta dist junto con los archivos d.ts apropiados.

El resultado final se parece a esto:

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

Npm vinculé la carpeta dist / mylib a la carpeta de mi proyecto VS 2015 / Angular 4.1.x.

Cuando intento compilar el proyecto en VS 2015, obtengo el mismo tipo de mensajes que se describen en algunas de las situaciones anteriores para Suscripción, Observable, etc.

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

Si elimino temporalmente el directorio node_modules del proyecto de la biblioteca, obtengo nuevos errores quejándose de no poder encontrar módulos:

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

Lo que me lleva a la conclusión de que cuando el compilador de mecanografiado compila la aplicación, sí busca en la carpeta node_modules del paquete de mi biblioteca vinculada las definiciones de módulo para mi biblioteca y no la carpeta de aplicaciones node_modules.

No tengo claro qué soluciones propuestas anteriormente proporcionarán una solución para este problema, ¿podría alguien ayudarme?

¡Gracias!

@mikehutter En su proyecto que usa su biblioteca (no en la biblioteca en sí), haga algo como esto en su tsconfig:

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

Es posible que necesite un ligero ajuste a esto dependiendo de dónde resulte su tsconfig y el código fuente.

(Como otros en este hilo, me encantaría ver alguna mejora en TypeScript que lo haga innecesario).

@mikehutter Recientemente agregamos algunas pautas en Angular CLI para trabajar con bibliotecas vinculadas, y parece que, en su caso, le falta la configuración de rutas de TypeScript para RxJ en su aplicación de consumidor. Consulte https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/linked-library.md para obtener más información.

@kylecordes está en el punto 👍

¡Gracias @kylecordes y @filipesilva! Eso era todo lo que necesitaba ...

¡Hola!

@mhegazy , ¿cree que esto llegará a 2.4 o es probable que vuelva a retrasarse?
Es realmente doloroso solucionarlo, lo que obliga a cada proyecto a definir siempre asignaciones de ruta para cosas que realmente no deberían importarle.

¡Realmente espero que esta vez esto llegue al lanzamiento!

Mejor,

No creo que esto se haya mencionado todavía, pero la forma súper abreviada de solucionar este problema es:

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

La entrada paths anterior básicamente dice: para cualquier módulo, primero búsquelo en la carpeta node_modules en la raíz del proyecto, luego vuelva a la regla normal (recorra de forma recursiva los directorios desde donde se ha producido la importación).

(Por favor, corríjame si me equivoco, todavía soy relativamente un recién llegado a TS).

La entrada en paths parece ser relativa a baseUrl . Entonces, si configura baseUrl para que esté en una subcarpeta, debe cambiar la definición de sus rutas en consecuencia. P.ej:

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

@fiznool fyi eso es parte de mis opciones de soluciones alternativas 2 y 3 (en mi publicación anterior). He visto que simplemente configurar la propiedad paths no es suficiente si tiene proyectos vinculados simbólicamente que usan los mismos tipos.

@jasonswearingen tu publicación es mucho más completa que la mía ... gracias por aclarar eso. Me aseguraré de volver a consultarlo si tengo más problemas. 😄

También estamos viendo esto en los proyectos de Google. Como se describe aquí:
https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -306969543

Las soluciones alternativas descritas anteriormente usando baseUrl y las rutas no parecen funcionar, tsc aún recoge las definiciones duplicadas y ninguna combinación de rutas / baseUrl / include / exclude / etc. ha podido convencerlo de lo contrario.

Tengo curiosidad por saber cómo funciona esto normalmente, si tiene un proyecto que depende de X, y también depende de Y que depende transitivamente de X, ¿cómo evita tsc cargar las definiciones de tipo dos veces?

@esprehn Le recomiendo encarecidamente que lea mi publicación de solución alternativa aquí: https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -302886203

con respecto a ese enlace, mis dos soluciones (2 y 3) requieren más que simplemente configurar la baseUrl y las rutas, así que si eso es todo lo que está haciendo, vuelva a leer. la forma "fácil" es la solución 2, pero mi preferencia es la solución 3, ya que permite una adecuada "navegación a la definición" a través de Visual Studio. el problema con la solución 3 es que solo necesita tener las definiciones .d.ts externas cargadas una vez en la cadena de dependencia.

Espero que ayude.

+1 Estoy usando lerna y una subdependencia con mecanografía incluida se marca como "duplicada" cuando se incluye a través de dependencias vinculadas.

Puedo compartir código si es necesario.

Con WebPack como en Angular-CLI, haga que Angular-CLI package.json haga referencia al paquete RXJS , luego elimine el paquete `RXJS 'del package.json de cualquier otro proyecto que no necesite debido al WebPack .

Esta situación puede ocurrir no solo con enlaces simbólicos, sino con npm-shrinkwrap.json en una dependencia con @types/node en dependencies . Shrinkwrap hace que npm instale dos versiones idénticas de @types/node en el paquete principal y en el empaquetado. Consulte https://github.com/KingHenne/custom-tslint-formatters/issues/5

También encontré esto al usar un proyecto de reacción que tiene @types/react instalado y vincularlo a una aplicación que también usa @types/react

Tenía el mismo problema mientras trabajaba con paquetes yarn link -ed.
Rx.js arrojaba un error: 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>'

Afortunadamente, lo resolví usando la misma versión Rxj.s en paquetes principales y vinculados.
Entonces, en mi caso, dos versiones diferentes de Rx.js causaron el problema.

Este es un gran bloqueador cuando se trabaja con monorepos. Realmente espero que esto no se demore más y llegue a 2.5.

Editar: 😮

image

Interesante. El monorepo es el único escenario en el que mi equipo NO encuentra este problema, porque los enlaces simbólicos apuntan todo a una carpeta de paquete común.

Mi equipo ha enfrentado este problema con bastante frecuencia al vincular nuestras propias bibliotecas internas durante el desarrollo.

Recientemente, encontramos una herramienta llamada yalc que mitiga esto muy bien y, de hecho,

Este problema parece retroceder continuamente. Debido a que esto es realmente perjudicial para los flujos de trabajo de muchas personas, ¿podríamos tener algún tipo de solución provisional, como un 'comentario de deshabilitación' como se sugiere en el # 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$);

El "comentario deshabilitado" no es mucho mejor que simplemente hacer conversiones de tipo en todas partes, lo cual es bastante doloroso en un proyecto grande. Arriba propuse el siguiente cambio de compilador:

Si TODAS estas condiciones son verdaderas, NO informe TS2345 para clases con miembros privados:

  1. Las firmas públicas son compatibles de acuerdo con la tipificación de pato de TypeScript habitual
  2. Las clases se definen en carpetas de paquetes NPM con el mismo nombre y versión (según package.json)
  3. Las clases tienen la misma ruta relativa para su módulo (por ejemplo, "./lib/blah/Bdts")

Si no se cumple alguno de estos criterios, está bien informar TS2345.

Una solución simplificada también sería mejor que la situación actual, por ejemplo, solo considere el n. ° 1, tal vez solo si la gente lo acepta a través de tsconfig. Debería ser bastante económico de implementar.

Este enfoque tiene la ventaja de simplemente deshabilitar las falsas alarmas, pero conservando la semántica existente. Mientras que los hacks de reasignación de node_modules cambian la resolución del módulo NPM de una manera potencialmente incorrecta (por ejemplo, provocando un mal funcionamiento del código en el ejemplo hipotético que di ).

Para ser honesto, ni siquiera estoy seguro de si esto debería ser "arreglado" en TypeScript, ya que también hay un problema con JavaScript simple: el operador instanceof devolverá falso si la clase del objeto difiere de la clase proporcionada.

Por lo tanto, prefiero esperar una mejor alternativa al enlace npm que tal vez se enganche primero en require ().

Esa es una buena idea. ¿Ha mirado pnpm ? Es un pequeño paso adelante con respecto al diseño actual de node_modules, pero muy efectivo si lo entiendo correctamente.

No se trata solo de npm link que se pueden reemplazar o no usar, sino de tener varias versiones del mismo paquete @types/xxx instaladas al mismo tiempo, a menudo extraídas de dependencias que proporcionan declaraciones de TypeScript que dependen en declaraciones estándar, como yo y otras personas informamos. El número de estos paquetes crecerá con una mayor adopción de TypeScript en la comunidad de Node.

@Yogu Creo que eso es confundir identidad e igualdad. Aunque las importaciones del mismo paquete / versión desde dos ubicaciones pueden representar dos instancias diferentes de un tipo, siguen siendo iguales en tipo.

Me viene a la mente el siguiente código (válido):

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

function foo (bar: a) {}

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

Lo mismo debería aplicarse a las bibliotecas que importamos.

Los tipos importados de las diferentes versiones de las bibliotecas (y los paquetes @types ) pueden ser iguales y diferentes (si la biblioteca se actualiza, la definición del tipo también debería actualizarse para reflejar los cambios).

Acabo de fusionar un cambio que intentará detectar paquetes duplicados según su nombre y versión, y usará solo uno. Pruébelo usando typescript@next la próxima vez que se publique.

¡Hurra, muchas gracias por arreglar esto! :-)

@pgonzal Gracias por el puntero a pnpm, ¡esto definitivamente parece interesante!

@sompylasar El @types/node es un caso un poco especial, pero para @types/react , aquí está mi sugerencia: Ponga todas las dependencias requeridas para la API de un módulo en el peerDependencies , no en dependencies . Esto deja en claro que las versiones de las dependencias deben coincidir (o al menos ser compatibles) entre el módulo principal y el secundario. Si tanto el padre como el hijo usan react pero no intercambian objetos de tipo react, este problema aquí no surgirá en primer lugar.

@harangue Si una clase se declara dos veces en dos archivos diferentes, con el mismo nombre y la misma estructura, todavía hay dos clases distintas que no son consideradas iguales por JavaScript. Como mencioné, el operador instanceof seguirá distinguiendo instancias de las dos clases.

Vea este violín para una demostración.

Esa es la razón por la que preferiría resolver esto en el nivel de NPM (para que no tengamos declaraciones múltiples en primer lugar si eso no está previsto) que en TypeScript.

@Yogu : +1: así que si @types/node es un caso especial, es decir, no puede ejecutar un programa usando dos versiones de nodo diferentes al mismo tiempo, será una versión, y muy probablemente la especificada en el paquete de nivel superior, tal vez TypeScript debería tratarlo como un caso especial, por ejemplo, ¿usar siempre el nivel superior @types/node para cada dependencia?

@ andy-ms ¡Gracias por esto!

Pruébelo usando

Supongo que eso no ha sucedido todavía. Lo he probado con un par de proyectos, pero hasta ahora no he tenido suerte. Sería genial ver una actualización en este hilo tan pronto como next esté disponible. @ andy-ms

Parece que las compilaciones diarias se han detenido nuevamente. El último fue: 2.5.0-dev.20170808 .

cc / @DanielRosenwasser

No estoy seguro de si esto está relacionado, pero cuando intento 2.5.1 parece que solo veo un aspecto de un módulo, incluso cuando tiene d.ts extendidos en otros lugares.

si tengo un @types para algo, digamos @types/mongodb y tengo una declaración personalizada que extiende ese módulo, es decir, agregando promisificación a los métodos, así que ahora tengo el @types/mongodb que tiene el módulo mongodb y tengo un archivo d.ts en mi proyecto llamado algo así como mongo-promisification.d.ts que contiene un módulo mongodb .

Entonces, con el escenario anterior, tengo un archivo que tiene import {somethingFromTypes} from "mongodb" se queja de que los datos del módulo de tipos no se pueden encontrar, aunque están allí y son válidos, pero si lo hice import {somethingFromMyExtendingDts} from "mongodb" eso funciona multa.

Al compilar, me dicen que el módulo no exporta esas cosas, cuando lo hace, también lo es este comportamiento deseado y solo necesito volver a exportar en mis d.ts personalizados o debería incluir tanto los tipos como la extensión d.ts ¿Yo tengo?

Estoy ejecutando la última versión de prueba (Windows 10 de 64 bits) y esto no parece estar solucionado para mí.

Reproducción

Estructura

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

correr

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

correr

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 Creo que el problema en tu situación es que tienes dos declaraciones de un módulo, donde lo que necesitas es un módulo y un aumento.
Debería poder hacer mongo-promisification.d.ts así:

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

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

Sin import , se encuentra en un contexto ambiental y está escribiendo una nueva declaración, no un aumento.

(Ref. Manual )

Puedo confirmar que esto me está funcionando ahora con [email protected] . Muchas gracias a @ andy-ms. ¡Esto es un cambio de juego!

Tuve el mismo problema, cuando estaba importando Observablea través de la biblioteca Typescript al proyecto angular-cli y las funciones estaban usando el fragmento de código

`` `función getitems (): Observable
http.get (). map (respuesta: Respuesta) => {
regresoresponse.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 Necesitaría un ejemplo completo para poder reproducir su error. Además, asegúrese de que está usando typescript@next - angular-cli puede tenerlo en una versión anterior que no tiene la función de deduplicación.

He intentado [email protected] pero sigo recibiendo muchos errores TS2300: Identificador duplicado.
Desafortunadamente, no puedo compartir todo el proyecto. Pero aquí hay algunos detalles:
tsconfig del paquete 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 del proyecto principal ( @croc/webclient es el paquete 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, ¿puedes reducir tu proyecto a un ejemplo simple que demuestre el problema?

@mhegazy aquí está
https://github.com/evil-shrike/typescript-npmlink-issue
en la raíz del proyecto:

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

luego en main :

npm run tsc

Hola @ evil-shrike, reduje el 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"
    ]
}

Así que terminamos incluyendo ambos (desde tsc --listFiles ):

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

Dado que node_modules proviene de include y no de la resolución del módulo, no creo que llamemos realpath en él, por lo que termina como dos archivos incluidos diferentes.
Es mejor no incluir su node_modules todos modos y, en su lugar, compilarlos por separado e importarlos de la misma manera que lo haría con cualquier otro paquete externo.

@ andy-ms
No es fácil de hacer. La biblioteca a la que se hace referencia en mi caso tiene muchos d.ts ambientales que, por ejemplo, amplían las interfaces globales. Como JQueryStatic:

interface JQueryStatic {
    cleanData (elems);
}

o declarar prefijos para cargado (requirejs):

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

Luego, en algún lugar de la fuente de lib, los usa:

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

Cuando tal módulo (de lib) se importará en algún lugar de main, fallará la compilación.

En la fuente de su biblioteca, debe usar las directivas /// <reference types="" /> (o /// <reference path="" /> ) para asegurarse de que las mecanografías necesarias estén presentes siempre que se importe su biblioteca. De esa forma, no tendrá que estar en "incluir"; cuando se importa, los tipos referenciados se agregarán automáticamente al proyecto.

@ andy-ms gracias, he refactorizado mi lib y ahora un proyecto donde npm-link-ed se está compilando bien.

No estoy seguro si estas son reproducciones demasiado grandes, pero obtengo lo mismo de una instalación básica de CLI con angular @ next y mecanografiado @ next que hacer con Observable<T> !== Observable<T> :

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

Blue importa y utiliza un componente y servicio de Red

@intellix ¿Podría obtener un ejemplo de errores usando solo la línea de comando tsc ? Es difícil saber qué versión de mecanografiado ng está usando.

@ andy-ms Todavía tengo este problema. Esto me ocurre cuando intento usar un enlace npm entre las extensiones vscode que estoy construyendo. Todos importan vscode que provoca errores de identificador duplicado.
TS Version 2.7.0-dev.20171118

Para mí funcionó, por ejemplo, mapear "rxjs / *" a una carpeta rxjs específica dentro de node_modules en la sección de rutas del archivo tsconfig.
Ahora todo funciona bien con npm link.

También he visto que esto sucede al pasar de un enlace simbólico a un enlace no simbólico de un enlace de actualización de versión a un paquete.

Vea esta pregunta SO también: https://stackoverflow.com/questions/38168581/observablet-is-not-a-class-derived-from-observablet

@dakaraphi @JoshuaKGoldberg ¿Podría

Con el nuevo comportamiento no deberíamos incluir un paquete si ya hemos visto otro paquete con el mismo valor de "versión" en su package.json . Si tiene varias instalaciones con diferentes versiones, obtendrá dos copias diferentes del módulo. Eso podría explicar por qué una actualización de la versión rompería esto, si solo afectara a una de dos instalaciones.

@ andy-ms El ejemplo que tengo son los siguientes repositorios:

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

Utilizo la instalación local de npm para hacer referencia a vscode-extension-common desde vscode-extension-fold

Si revisa estos repositorios, actualmente funcionan porque tengo una solución alternativa de mapeo de ruta en el package.json de vscode-extension-fold . Sin embargo, si lo entiendo correctamente, no debería necesitar esa solución.

@dakaraphi ¡Gracias! Parece que el error se debe a que vscode.d.ts se escribe como una declaración ambiental global en lugar de como un módulo externo. Creé Microsoft / vscode-extension-vscode # 90.

Esto todavía no me funciona cuando intento vincular 2 paquetes, cada uno con una dependencia de rxjs . Estoy usando [email protected] y [email protected] . Ambos paquetes utilizan exactamente la misma versión. ¿Alguien tiene una solución para esto?

@SamVerschueren ¿Podría proporcionar instrucciones específicas para reproducir el error? También prueba con typescript@next .

@ andy-ms. ¡Veré qué puedo hacer!

@ andy-ms Aquí hay un pequeño repositorio de reproducción https://github.com/SamVerschueren/ts-link-6496. Usé [email protected] para reproducir esto.

  1. Instale ambas dependencias para mod-a y mod-b
  2. Compile mod-b con yarn build
  3. Compile mod-a con yarn build

El paso 3 fallará con el siguiente error

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.

Todavía me encuentro con este problema con [email protected]. También probé typecript @ next y tuve el mismo problema.

La raíz del problema parece ser que los paquetes vinculados todavía hacen referencia a las definiciones de tipo en su propio node_modules local en lugar de usar las mecanografías del node_modules al que están vinculados, cuando sea posible. Eso combinado con el hecho de que:

  1. los globales no se pueden redefinir

    • esto hace que el compilador se queje cuando el global se define tanto en el node_modules como en el node_modules en el paquete vinculado

  2. las clases que de otro modo son idénticas no se pueden asignar entre sí

    • esto hace que el compilador se queje al intentar asignar una variable cuyo tipo es una clase del proyecto principal node_modules a un valor devuelto por el paquete vinculado cuyo tipo está definido en su propio node_modules

He podido solucionar este problema utilizando la variable de configuración paths . Para los módulos cuyas definiciones provienen de @types/* , como se sugiere aquí , simplemente puede usar:

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

En el caso de que se encuentre con este problema con un paquete que viene con definiciones de tipo que definen clases o globales, debe agregarlas manualmente. Por ejemplo, rxjs :

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

También tengo problemas con los enlaces simbólicos cuando agrego un paquete local, usando TS 2.8.3:

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

Desde v3, npm aparentemente los está instalando con enlaces simbólicos en lugar de copiar los archivos.

Sin embargo, cuando intento compilar, el compilador ve el archivo de definición vinculado como dos archivos separados y en conflicto:

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 copio manualmente los archivos en su lugar, funciona como se esperaba. Puedo solucionar esto configurando typeRoots: ["./node_modules/**/"]

¿Fue útil esta página
0 / 5 - 0 calificaciones