Typescript: Повторяющиеся объявления типов со ссылкой npm

Созданный на 15 янв. 2016  ·  147Комментарии  ·  Источник: microsoft/TypeScript

Использование TypeScript 1.7.3.

Предположим, у меня есть следующие пакеты npm.
Файлы объявлений генерируются компилятором TypeScript, и на них ссылаются другие пакеты описанным здесь способом.

пакет-а

ts src:

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

объявление ts:

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

пакет-b (зависит от пакета-a):

ts src:

import ClassA from 'package-a';

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

объявление ts:

import ClassA from 'package-a';

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

package-c (зависит от package-a и package-b):

ts src:

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

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

Последняя строка вызывает ошибку при компиляции:

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

Когда я удаляю строку private foo; из объявления package-a, TypeScript не выдает никаких ошибок.
Однако этот обходной путь немного болезненный.

Я понимаю, что раскрытие частных свойств объявлению сделано намеренно (https://github.com/Microsoft/TypeScript/issues/1532).
Я думаю, что TypeScript должен игнорировать частные свойства при компиляции назначения переменных.
Или есть лучший способ решения этой проблемы?

@types Bug Fixed

Самый полезный комментарий

Я только что объединил изменение, которое попытается обнаружить повторяющиеся пакеты на основе их имени и версии и использовать только один. Пожалуйста, попробуйте его, используя typescript@next когда он будет опубликован в следующий раз.

Все 147 Комментарий

Здесь есть только одно корневое объявление ClassA , поэтому этой ошибки не должно быть.

Извините, я обнаружил, что это связано с npm link .

Когда я использую npm link , пакеты устанавливаются, как показано ниже, поскольку он просто создает символические ссылки.

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

Как показано, похоже, что есть два разных файла объявлений для package-a.
Если я обычно устанавливаю пакеты с помощью npm install , этого не произойдет, потому что в этом случае объявление package-a не включено в package-b.

Я надеюсь, что для этого все равно будет какое-то решение, но это может быть сложно и не приоритетно.

В итоге я не использовал npm link , и для меня это больше не имеет значения.

Достаточно честно, но может кто-то другой: wink:

на самом деле на диске есть два файла с двумя объявлениями ClassA. так что ошибка верна. но нам нужно учитывать модули узлов при сравнении этих типов. об этой проблеме уже сообщалось ранее в https://github.com/Microsoft/TypeScript/issues/4800 , для Enums мы изменили правило на полу-номинальную проверку. возможно, сделайте то же самое для классов.

+1 по этому поводу с TS 1.7.5 со всеми соответствующими пакетами, связанными с NPM. Я попытался создать тестовый сценарий, в котором обнаружена проблема, но не смог. Независимо от того, что я пробовал, TS был в порядке со сценарием, который, как я вижу, терпит неудачу с TS2345 в моем приложении, и, насколько я мог судить, все копии проблемного файла .d.ts были символическими ссылками на один и тот же файл, поэтому не должно были разные объявления внутри типа. Однако было бы неплохо, если бы ошибка, выдаваемая Typescript, ссылалась на файлы, в которых объявлены два несовместимых типа, поскольку это могло бы пролить свет на то, что я не рассматриваю. Прямо сейчас он говорит, что есть два определения, но ничего не делает, чтобы помочь разработчику точно определить проблему.

В качестве обходного пути вы можете использовать <any> в конфликтующем выражении, чтобы пропустить проверку типа. Очевидно, это может потребовать от вас сделать аннотацию другого типа, где вам, возможно, не приходилось раньше. Я надеюсь, что кто-нибудь сможет изолировать эту проблему в какой-то момент.

РЕДАКТИРОВАТЬ: ясно, что в моем случае используется ссылка NPM

Замеченный TS 1.8 доступен, обновлен, и проблема все еще существует в этой версии.

Спасибо за всю работу по анализу и документированию этой проблемы. У нас такая же проблема с некоторыми из наших кодовых баз. Мы перенесли некоторые проекты для правильного использования зависимостей package.json но теперь это наблюдается при использовании npm link во время разработки.

Могу ли я чем-нибудь помочь решить эту проблему?

Я использую Lerna, который связывает пакеты с символическими ссылками, и тоже вижу проблему. Машинопись версии 2.0.3.

К сожалению, Lerna и его символические ссылки являются жестким требованием, поэтому я использовал этот неприятный обходной путь, чтобы заставить его компилироваться нормально, при этом все еще сохраняя правильную проверку типов потребителями:

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

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

Класс очень маленький, поэтому он не был таким сложным, и я не ожидаю, что он когда-либо изменится, поэтому я считаю это приемлемым обходным путем.

К вашему сведению, я тоже оказался здесь в результате использования npm link и получения этой ошибки. Кто-нибудь нашел обходной путь для этого?

@xogeny, можете ли вы рассказать, как ссылка npm вызывает у вас эту проблему?

@mhegazy Я начал получать эти ошибки, подобные приведенной выше (за исключением того, что я использовал Observable из rxjs , т.е. «Тип 'Observable' не может быть назначен типу 'Observable'). Это, конечно, это выглядело странно, потому что два, на которые я ссылался, Observable из одной и той же версии rxjs в обоих модулях. Но там, где типы "встретились", я получил ошибку. Я покопался и в конце концов обнаружил эту проблему, когда @kimamula указал, что если вы используете npm link , вы получите эту ошибку. Я, как и другие, работал над этим (в моем случае я создал дублированный интерфейс только с той функциональностью, которую я необходимо в одном модуле, а не в ссылках rxjs ).

Это ответ на ваш вопрос? Я спрашиваю, потому что не думаю, что мой случай выглядит иначе, чем другие здесь, поэтому я не уверен, поможет ли это вам.

Мы проделали работу в TS2.0 специально для включения сценариев npm link (см. Https://github.com/Microsoft/TypeScript/pull/8486 и # 8346). У вас есть образец, где я могу посмотреть, где ссылка npm все еще не работает для вас?

Ага. У меня 2.0.3 (проверил). Попробую создать воспроизводимый случай.

Кстати, вы должны следить за этими темами, поскольку они подразумевают, что это все еще проблема, начиная с TS 2.0:

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

Проблема, которую я вижу в моем репозитории Lerna, несколько связана с этим, поэтому я сделал ее урезанную версию на https://github.com/seansfkelley/typescript-lerna-webpack-sadness. Возможно, это даже ошибка webpack / ts-loader, поэтому я также отправил туда https://github.com/TypeStrong/ts-loader/issues/324 .

Я использую машинописный текст 2.0.3 и вижу эту ошибку в Observable, как описано выше, например

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

Я также попадаю в пакет Lerna monorepo. Похоже, что большинство, но не все части системы типов используют реальный путь для однозначной идентификации файлов. Если вы спуститесь по ветке, которая использует путь символической ссылки, а не реальный путь, вы получите идентичные, но разные типы.

Это довольно серьезная проблема, которая затронет только более сложные кодовые базы, и кажется невозможным обойти ее без принятия радикальных мер, поэтому я надеюсь, что смогу убедить вас всех уделить ей то внимание, которого она заслуживает. 😄

Это особенно заметно в тех случаях , когда у вас есть приложение , которое зависит от зависимостей А, зависимость А зависит от зависимостей В и вендов объекты , которые содержат типы из зависимостей В. приложения и зависимостей А как npm link Dependency B и ожидать , чтобы быть возможность импортировать из него типы и заставлять их описывать одно и то же.

Это приводит к появлению глубоких сообщений об ошибках, и я нахожусь на грани того, чтобы пройти и удалить все свойства private и protected в моих библиотеках, потому что я уже потерял так много времени на это :

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)

Я очень признателен вам всем, кто заглянул в это. благодарю вас!

@tomdale вы используете Webpack, tsc или другой инструмент сборки? Моя проблема, похоже, возникает только при компиляции через Webpack (см. Связанный репо из моего предыдущего комментария ).

@seansfkelley Это похоже на https://github.com/TypeStrong/ts-node.

Правильно, он использует ts-node (для корневого приложения). Однако зависимости представляют собой пакеты, скомпилированные с помощью tsc .

Я только что столкнулся с этой проблемой, и это серьезная проблема для нас, потому что мы пытаемся разделить наш сервер на множество небольших библиотек. Во время разработки нам часто нужно связать наши репозитории с помощью npm. Конкретная проблема, с которой я столкнулся, побудила меня найти это использование rxjs Observables и интерфейсов:


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

Это работает, если я не npm link , но когда я это сделаю, я получаю:

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

Единственное, что я могу сделать, это избегать private . Я больше не публикую пакеты с private из-за этой проблемы, а просто использую вместо них префиксы _ стиле JavaScript. Я столкнулся с этим с https://github.com/Microsoft/TypeScript/issues/7755, который является аналогичным обсуждением того, почему private попадает в систему номинального типа, а не в структурную, и поэтому запретил его на моем собственные проекты, потому что слишком легко получить различия в версиях (например, NPM 2 или использование npm link ).

@blakeembrey, когда вы говорите «

@jeffwhelpley Да, извините, вы не виноваты. Это Observable . К сожалению, совет избегать private очень невелик и не совсем применим к вам 😄 Возможно, вы можете поднять вопрос, я полагаю, rxjs об использовании private в их публичных интерфейсах?

Изменить: я в основном комментировал, потому что раньше следил за проблемой и избегал присоединяться к своему собственному опыту, но решил, что могу снова записать свои мысли, вместо этого они похожи на https://github.com/Microsoft/TypeScript/issues/ 6496 # issuecomment -255232592 (где @tomdale предлагает удалить private и protected , я сделал то же самое некоторое время назад).

У меня сложилось впечатление от @mhegazy, что он считает, что с npm link нет проблем. Но, похоже, это все еще беспокоит нас и других. Так что я не уверен, где стоит эта проблема? Это общепризнанная проблема с TS 2.0+ или мне просто где-то не хватает обходного пути?!?

У меня такая же проблема, и она не вызвана npm link . Я все равно получу его, если установлю с помощью npm install file.tar.gz . Вот ошибка:

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

Вот как выглядит мой 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);
  }

Он жалуется на строку this.user$ . Stormpath имеет user$ определенное следующим образом:

@Injectable()
export class Stormpath {

  user$: Observable<Account | boolean>;

@xogeny Странно, я понял, что идентификация определения была привязана к местоположению файла, что означало бы, что они всегда будут вызывать проблемы с использованием npm link (потому что для зависимости npm link ed будут установлены собственные зависимости) . Возможно, идентификация определения была изменена - использование хэшей файлов может быть хорошим решением в TypeScript. К сожалению, существует всего дюжина различных способов получить дублирующиеся модули в JavaScript ( npm install из GitHub, npm install , ручные клоны, конфликты версий могут даже привести к тому, что одна и та же версия окажется в разных местах из-за как работает алгоритм разрешения модуля узла и т. д.).

@blakeembrey Возможно. Но тогда о чем это было?

Заметьте, я не жалуюсь. Я просто пытаюсь понять, есть ли надежда на то, что это разрешится или нет. Это серьезная проблема для нас по всем причинам, упомянутым @jeffwhelpley .

@xogeny Я знаю, я тоже пытаюсь, мне бы хотелось, чтобы он разрешился правильно 😄 Я прочитал связанные проблемы, но все они предназначены для разрешения реального пути символической ссылки, что подразумевает наличие двух (реальных) файлов они по-прежнему будут конфликтовать, потому что они перейдут в разные места. Вот что происходит, когда вы npm link переходите из одного проекта в другой, поскольку оба будут иметь свои собственные зависимости, которые могут отличаться от повторно экспортированных символов из пакета npm link ed.

Изменить: я могу подтвердить, все проблемы из-за двух файлов. npm link вызовет его, потому что просто иметь зависимость в репо, которое вы только что связали, это та же зависимость, что и в проекте, с которым вы связались. Простым воспроизведением будет выполнение npm install одной и той же зависимости на двух разных уровнях приложения и наблюдение за их ошибками.

image

Для всех, кто следит за этой веткой ... Я попробовал обходной путь, описанный здесь, и, похоже, он работает (пока).

Я воспроизвел эту ошибку.

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

Поскольку есть две установки rxjs , получаем:

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

У меня есть обходной путь, который отлично работает для командной строки, но визуальная студия по-прежнему не работает: https://github.com/Microsoft/TypeScript/issues/11107#issuecomment -254003380

мой новый обходной путь для Windows + Visual Studio 2015 - это роботизированное копирование моей папки xlib Library src и dist папки node_modules\xlib\src и node_modules\xlib\dist потребляющего проекта.

вот значительная часть моего сценария пакетного файла robocopy, если кому-то это нужно:

: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

Приносим извинения за повторную ошибку с этой проблемой, но это серьезное препятствие для нашего проекта, поскольку он не может выполнить npm link пока мы вносим изменения. Я хотел бы помочь с PR, если бы один из нынешних участников TypeScript мог дать мне небольшое руководство о том, с чего начать поиск в кодовой базе.

Я тоже борюсь с этим. Мы адаптировали TS, начиная с небольшого приложения, теперь мы разделили его на подмодули, связали их и… БУМ. TS больше не компилируется. Это все еще проблема для всех dist-тегов TS? В настоящее время я испытываю это в @rc (2.1.1).

@heruan и @jeffwhelpley, не могли бы вы typescript@next , мы исправили несколько связанных проблем. и если вы все еще видите проблему, предоставьте дополнительную информацию о настройке вашего проекта.

@mhegazy У меня Version 2.2.0-dev.20161129 но проблема не исчезла . Конкретная проблема заключается в том, что у меня есть один проект (назовем его ProjectA), который содержит «интерфейс» (с использованием класса, но это значит, что я могу использовать класс в качестве токена для Angular 2 DI) следующим образом:

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

Затем в совершенно отдельном проекте (назовем его ProjectB), в котором есть класс, реализующий интерфейс из первого проекта следующим образом:

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
}

Когда я выполняю обычную компиляцию машинописного текста для ProjectB, он отлично работает. Но если я npm link ProjectA из корневого каталога ProjectB, а затем снова запустил tsc я получу:

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

Я не мог воспроизвести в фиктивном проекте, думаю, мне не хватает причины проблемы, поэтому я не могу ее воспроизвести. @jeffwhelpley, можете ли вы опубликовать фиктивный проект, воспроизводящий проблему? Я думаю, что проект Lerna должен быть прекрасным и легко тестируемым.

@heruan Я постараюсь это настроить.

Во-первых, к вашему сведению. Думаю, я нашел обходной путь. Проблема решена, если я npm link rxjs в ProjectA, и в ProjectB. Это имеет смысл, потому что в этом случае и ProjectA, и ProjectB используют одни и те же файлы rxjs. Без этого они технически используют разные файлы (хотя и одну и ту же версию):

Если вы просто npm link ProjectA из ProjectB, тогда:

  • ProjectB указывает на node_modules / rxjs
  • ProjectA существует как символическая ссылка в node_modules / ProjectA, а rxjs, на которые он ссылается, находится в node_modules / ProjectA / node_modules / rxjs

Но если вы используете npm link rxjs в обоих случаях, то обе ссылки на rxjs будут символически привязаны к одному и тому же глобальному местоположению npm.

В любом случае, это явно не идеал, но, по крайней мере, то, что может продвинуть нас вперед.

Также ... не уверен, актуально ли это или имеет значение (увидим, как только я настрою тестовый проект), но две мои библиотеки (например, ProjectA и ProjectB) на самом деле являются частными репозиториями npm.

Спасибо @jeffwhelpley за подсказку, но поскольку я использую Lerna, все модули уже связаны друг с другом, поэтому они читают один и тот же файл, но я думаю, что компилятор TS принимает во внимание путь ссылки, а не настоящий. Я могу ошибаться, так как я не могу воспроизвести на макетном проекте, и я действительно схожу с ума ...

Кто-нибудь здесь может решить это элегантным образом?

Также обратите внимание, что это проблема не только с npm link , вы также столкнетесь с этой проблемой в производственных сборках, когда ваши общие зависимости указывают на другую версию.

т.е. ProjectA требуется [email protected] а ProjectB использует [email protected]

Когда вы устанавливаете ProjectA в качестве зависимости в ProjectB, у вас тоже будут дублированные типы, так как, например, будет два объявления Observable , одно в node_modules/rxjs и одно в node_modules/project_a/node_modules/rxjs

Вы можете обойти это, разрешив версии rxjs в ProjectA быть чем-то вроде ~4.9.0 , так что npm install не нужно загружать собственную версию, и вместо этого будет использоваться версия ProjectB. Но имейте в виду, что это не только проблема рабочего процесса разработки.

Проводка здесь в @ ANDY-МС предложение . Вчера попробовал еще раз с последней версией 2.0.x и все еще имел.

Я получаю это с типами для Angular 1: https://github.com/DefinitiTyped/DefinentyTyped/issues/10082#issuecomment -253023107

Сегодня снова займемся этим, особенно проблемой с символическими ссылками. Моя настройка примерно такая:

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

Если у меня просто @types/angular , tsc работает нормально. Если у меня есть весь набор ( @types/angular-{animate,cookies,mocks,resource,route,sanitize} ), я начинаю получать множество ошибок типа:

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

Я исправил это, добавив базовый ../../node_modules/@types как typeRoots к моему tsconfig.json :

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

Я попытался добавить локальный node_modules/@types , но это не сработало.

@heruan, один хакер, который я начал делать, - это реализовать свой собственный скрипт npm для связывания / отмены связывания вместо использования функций lerna. Итак, вы можете сделать что-то вроде lerna run link а затем во всех ваших файлах package.json у вас есть сценарий npm с именем link который выполняет все ссылки npm, включая (в моем случае) npm link rxjs . Кажется, работает нормально, не совсем идеально.

@jeffwhelpley, можешь поделиться здесь своим решением?

@yvoronen Я не могу поделиться всем своим кодом, но мое решение описано выше. На высоком уровне ключевой момент, который я нашел, - это обязательная ссылка на npm не только на все локальные проекты, над которыми вы работаете, но и на ссылку npm на внешние библиотеки, которые могут вызывать проблему (в моем случае проблема связана с rxjs из-за частные вары в объекте Observable). Итак, я использую lerna для управления всеми своими локальными проектами, а затем запускаю lerna run link . Под сценой это вызывает npm run link в каждой из корневых папок моего проекта. Итак, вам нужно, чтобы сценарий link определен в вашем package.json следующим образом:

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

Надеюсь, это имеет смысл, но дайте мне знать, если у вас возникнут вопросы.

Я хотел предоставить обновление. Вот о чем мы думаем из разговора с

  • Одно из решений, которое мы рассматриваем, - это концепция различения пакетов на основе их версии, а также имени их разрешения. У меня нет полной информации о том, что будет с этим связано.
  • Другой - просто полностью расширить путь, чтобы получить «истинную» идентичность символической ссылки. Я считаю, что это проще, но более ограниченно, когда дело доходит до работы с одним и тем же пакетом в разных версиях, но помогает решить приличное количество случаев.

Вы уверены, что ваш комментарий относится к этому вопросу? Это звучит полностью
другой.

12 января 2017 г. в 3:14 Nikos [email protected] написал:

Обратите внимание, я не использую типы или ссылку npm AFAIK.

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

-
Вы получили это, потому что оставили комментарий.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment-272137732 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AAUAmcMXodOvU7coymMqGzTofD4pMagpks5rRgsogaJpZM4HFcWl
.

@dobesv это на самом деле вся причина, по которой вы вообще видите проблему. TypeScript распознает объявление класса как два отдельных объявления, потому что он не может отличить путь с символической ссылкой от истинного пути. Решение - либо

  1. Разверните символическую ссылку.
  2. Убедитесь, что содержащий пакет тот же самый.

@DanielRosenwasser Извините, мой комментарий был ответом на чей-то комментарий "В четверг, 12 января 2017 г., 3:14 AM Nikos @ . * > Написал" ... кто это и что они сказали, я больше не помню, я считаю, что они спрашивали о какой-то проблеме в этой ветке комментариев, которая не имела ничего общего со ссылкой npm.

Но пока я здесь, я должен упомянуть, что есть что-то забавное в том, как имя файла играет роль в типах. Сегодня у меня была проблема с RxJS, когда он жаловался, что такой-то метод не был определен в Observable. Причина в том, что у HTTP-библиотеки была своя собственная копия rxjs, которая отличалась от всех остальных. Фактически, я нашел четыре разных копии rxjs в моем дереве node_modules.

Это кажется проблематичным подходом, который будет оставаться проблемным и запутанным.

Если вся эта концепция имени файла, каким-то образом играющая роль в идентичности типа, исчезнет, ​​я думаю, что эта проблема с npm-ссылками также исчезнет.

Я все еще не уверен, как это будет работать ... Я новичок в TypeScript. Но такое впечатление, которое у меня складывается, состоит в том, что эта вещь "имя файла имеет значение" вызвала у меня некоторую путаницу в связи с библиотеками, которые я использую (ionic2, angular2 и rxjs).

Проблема в том, что имя файла по-прежнему является идентификатором модуля в Javascript, поэтому оно не может исчезнуть полностью. Может ли кто-нибудь подробно рассказать о проблемах с использованием канонического пути (разрешение символической ссылки) в отношении нескольких версий пакета? Если в дереве есть несколько версий пакета, у них будет несколько канонических абсолютных путей, верно?

РЕДАКТИРОВАТЬ: Я понял это после публикации, и этот комментарий хорошо подводит итог:
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -257016094

exclude и compilerOptions.typeRoots полностью игнорируются tsc. Я пробовал все комбинации, чтобы он игнорировал пути с символическими ссылками, но он просто не
он видит модуль как совершенно другой путь, как будто он разрешает символическую ссылку и не понимает исключенные шаблоны.

например, у меня G:\www\cim-service-locator npm связано с npm link cim-service-locator . на моем пути к проекту в G:\www\cim-backend ошибки отображаются следующим образом:

crop

Я пробовал все возможные комбинации excludes / includes / typesRoot, но не смог заставить tsc игнорировать их. с использованием 2.2-dev.20170131

Мы столкнулись с этой проблемой как при использовании «ссылки npm» (из-за проблемы SPFx, о которой сообщил @waldekmastykarz), так и без «ссылки npm» (см. Ошибку № 11436).

В конце концов я понял, что строгость компилятора TypeScript связана с несовместимостью, которая реально может возникнуть из-за дурацкого дизайна папки

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]

В этом примере B @ 2 должен быть установлен во вложенных папках, чтобы избежать конфликта с зависимостью A от B @ 1 . Теперь предположим, что ClassB расширяется от ClassE, и у нас есть что-то вроде этого:

B / package.json

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

Если package.json C «s просит [email protected] , затем две копии ClassB могут в конечном итоге с различными реализациями базового класса, что означает , что они на самом деле несовместимы. Код может выйти из строя во время выполнения, если вы попытаетесь использовать их взаимозаменяемо.

В этом примере TS2345 предотвратит эту ошибку, и это хорошо. Однако это НЕ существенно: если бы компилятор рассматривал две копии ClassB как эквивалентные, его система типов все равно была бы внутренне согласованной и имела бы детерминированное поведение.

Это важно, потому что для нас TS2345 в основном выдает ложные срабатывания. Эти ложные срабатывания вынуждают людей писать «как все» везде, где у них общие типы пакетов NPM, что вызывает другие ошибки. Таким образом, строгость создает больше проблем, чем решает.

Хочу предложить следующее исправление:

Если ВСЕ эти условия верны, НЕ сообщайте TS2345 для классов с закрытыми членами:

  1. Публичные подписи совместимы в соответствии с обычной утиной типизацией TypeScript.
  2. Классы определены в папках пакетов NPM с тем же именем и версией (согласно package.json).
  3. Классы имеют одинаковый относительный путь для своего модуля (например, "./lib/blah/Bdts")

Если какой-либо из этих критериев не выполняется, можно сообщить о TS2345.

@iclanton @ nickpape-msft

Ошибка @seansfkelley Webpack отслеживается TypeStrong / ts-loader # 468

Привет, ребята,
Кто-то нашел решение ??
У меня такая же проблема, когда я связываю один проект с другим с помощью RxJS.
Благодаря ;)

Привет, временный обходной путь - обернуть Observables, возвращаемые зависимостью, в Observable#from .

Пока нет решения. ?

Похоже, здесь есть две проблемы.

Пользователи ts-loader, получающие ошибочные ошибки из-за повторяющихся определений, по-видимому, вызваны неверным вводом в API компилятора. Исправление для этого доступно в TypeStrong / ts-loader # 468.

Другая проблема заключается в том, что у вас есть один и тот же пакет (тот же пакет npm + версия), установленный дважды локально в файловой системе (без использования npm link ) в двух вложенных папках, либо с перечислениями, либо с классами с частными членами, сравнивая типы из этих двух пакетов не будут работать как несовместимые.
Эта проблема немного сложнее и потребует от компилятора дополнительной работы по «дедупликации» пакетов перед их обработкой.

Если ни одна из этих двух категорий не применима к вам, сообщите о новой проблеме и предоставьте нам достаточно информации, чтобы воспроизвести проблему локально, и мы будем рады провести дальнейшее расследование.

Известный обходной путь - использовать многопроектное решение, которое устранит повторяющиеся папки, то есть гарантирует, что обе подпапки node_modules в конечном итоге будут символически связаны с одной и той же целью.

Раш (который мы используем) и Лерна являются примерами.

@smcatala Вы можете объяснить свое решение. Мне нужно это срочно исправить. Благодарю.

@ leovo2708
модуль 'foo':

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

клиентский код в другом модуле, который зависит от модуля 'foo':

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

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

@ leovo2708 простое решение - не использовать npm link .

используя ts 2.1, я смог использовать ссылку npm с одной библиотекой (назовем ее xlib , это мой реальный пример), но вам нужно будет убедиться, что модули, которые ваша библиотека ( xlib ) нагрузки не дублируются в папке node_modules проекта-потребителя.

Я делаю это следующим образом

  1. удалить node_modules
  2. npm link xlib который создает символическую ссылку на xlib в node_modules моего потребляющего проекта
  3. npm install который устанавливает оставшиеся зависимости моего консумного проекта

Я на самом деле не слежу за этим разговором и не проверял, изменилась ли / изменилась ли эта проблема с версии 2.2, но я бы поделилась своим обходным путем для ts 2.1

На случай, если это будет полезно, я собрал здесь минимальное воспроизведение нескольких определений случая перечислений: https://github.com/rictic/repro-npm-link-typescript-issue

@mhegazy Мы действительно видим

Большое спасибо, надеюсь, что это скоро будет исправлено. Однако я использовал новое решение, дублировал любые файлы с помощью Observable. Это нехорошо, но временное решение.

tsconfig.json предоставляет отображение пути, добавляет повторяющиеся зависимости в paths , поэтому он будет загружен из правого node_modules вместо связанного.

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

Не уверен, что здесь уже упоминалось, но это решение сработало для меня: https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001

Это в основном то же самое, что и решение @charpeni выше, за исключением без префикса «../» в путях. (что кажется странным, ведь разве это не означало бы, что файл tsconfig.json находится в подпапке корня проекта?)

Отличная идея @charpeni. Я использовал эту настройку путей для решения различных других похожих проблем, но она также кажется идеальной для этой. Фактически, мне интересно, может ли правильная настройка paths в проекте-потребителе (а не в каждом потребляемом проекте) отвлечь компилятор TypeScript от следующего разрешения узла. Если это сработает, это будет взлом O (1) вместо взлома O (n). По сути, такая схема будет запускать статическое разрешение узлов, а затем помещать результаты в tsconfig.

Я полупублично экспериментирую с этими вещами, если кто-то хочет посмотреть (или помочь ...). Я, вероятно, попробую следующую идею.

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

Для упрощения использования вы также можете установить такие пути:

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

Ссылка npm является важной частью рабочего процесса при работе с несколькими пакетами в отличие от архитектуры монорепо. TS должен иметь возможность видеть, что два пакета идентичны, а не ошибка

@charpeni Я не мог заставить работать обходной путь. Чтобы было ясно, к какому tsconfig.json это нужно добавить? Корневой пакет или связанный пакет?

У меня тоже возникла эта проблема. Это внезапно начало происходить в понедельник, и я не знаю почему. Это действительно затрудняет разработку, особенно когда речь идет о разработке пакетов для наших проектов. Я пробовал множество обходных путей, чтобы исправить это. Запуск mklink /j в Windows по-прежнему вызывает эту проблему, поэтому это не проблема ссылки npm. Если у кого-то есть обходной путь или исправление, это будет большим подспорьем.

Мое обходное решение - связать npm каждый «дублированный» пакет как в корневом пакете, так и в зависимости, потому что тогда они снова ссылаются на одни и те же файлы.

Кстати, эта проблема не имеет ничего общего с @types

В итоге мы использовали паттерн глобус.

@felixfbecker Для реализации он доступен здесь: https://github.com/sherweb/ng2-materialize/blob/master/demo-app/tsconfig.json#L19 -L22

У меня аналогичная проблема, за исключением того, что она полностью связана с @ types / node.

libA зависит от @ node / types
libB зависит от libA и @ node / типов
libC зависит от libA, libB и @ node / типов

libA строит нормально.
libB npm связана с файлом сборки libA.
libC npm, связанная с libA и libB, не выполняет проверку типов с такими ошибками, как

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

Я безуспешно пытался возиться с "типами" и "корнями типов".

@charpeni Похоже, ваш проект также зависит от @ types / node. У вас есть представление о решении моей проблемы или обходном пути?

@nicksnyder, это может быть связано с тем, что они имеют разные версии, а @types/node является глобальным объявлением, что означает, что вы не можете определять одни и те же имена дважды. По этой причине для пакетов лучше _не_ зависеть от типов среды, они должны предоставляться пользователем:
https://github.com/Microsoft/types-publisher/issues/107

@nicksnyder У меня была аналогичная проблема, и я смог обойти ее, связав npm все три проекта с одной установкой @ types / node. Поскольку определения затем определены в одном файле, они больше не дублируются.

@felixfbecker Я

FWIW libA - это https://github.com/Microsoft/vscode-languageserver-node/tree/master/jsonrpc , libB - это https://github.com/Microsoft/vscode-languageserver-node/tree/master/client и libC это мое собственное расширение VS Code.

@uncleramsay, как именно вы, npm link @types/node ?

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

Я хотел бы создать решение для связывания, но я также обошел его, удалив зависимость @ types / node в libA и libB, и добавил refs.d.ts, который содержит локальные ссылки на копию узла libC.

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

Я обнаружил, что смог решить возникшие у меня проблемы из описания в комментарии в https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -225303098

мы только добавили поддержку разрешения символических ссылок для модулей ...

В разных местах кодовой базы, когда мы использовали два разных стиля ссылок:

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

Эти два несовместимы в случае, когда node_modules символически связаны, поскольку разрешение модуля (с types= ) расширяется до реального пути, а path= - нет. Это приводит к двум различным файлам, на которые ссылаются при компиляции с помощью tsc --listFiles , символической ссылки и реального пути.

Мы решили использовать одно или другое, но не оба сразу. Это также помогло указать typeRoots: [] в tsconfig, чтобы компилятор не загружал автоматически типы из node_modules/@types в случае использования стиля reference path= .

Я считаю, что в будущем предпочтение будет отдаваться стилю types= (по крайней мере, для нас).

В идеале, однако, предпочтительнее было бы развернуть реальный путь в reference path= и проверить дублирующиеся совпадающие пути, чтобы избежать таких проблем.

Надеюсь, это кому-то поможет.

@nicksnyder, у вас должно получиться что-то вроде этого:

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

Таким образом, B и C указывают на те же самые файлы, что и A.

@unclerams, может быть, имейте в

Разве одноранговые зависимости не могут быть решением этой проблемы?
http://codetunnel.io/you-can-finally-npm-link-packages-that-contain-peer-dependencies/

Одноранговые зависимости были изобретены для ситуации, когда плагин хочет сказать, с чем он связан. В этом случае они вроде как работают. Но они вызывают много проблем, если люди начинают преобразовывать все свои зависимости в одноранговые, надеясь избежать дублирования "npm install".

Мы месяцами изгоняли их из наших внутренних репозиториев git. При использовании, как я думаю, вы предлагаете, одноранговые зависимости позволяют решить проблему параллельного управления версиями, обменивая ее на несколько новых проблем:

  • все дерево инвертировано, то есть каждый пакет теперь становится ответственным за принятие жесткой зависимости от пакетов, которые раньше были косвенными зависимостями, во многих случаях без понятия, для чего он нужен

  • если удалена одноранговая зависимость, эти жесткие зависимости, вероятно, никогда не будут удалены

  • авторы пакетов склонны использовать широкий диапазон шаблонов своих одноранговых версий, утверждая, что работают с версиями, с которыми они никогда не тестировали; сломанные сборки внезапно становятся проблемой потребителя

Хорошо сказано.

обходные пути

Вот 3 варианта обходных путей, которые я использовал:

вариант 1: используйте vscode, а не Visual Studio

Компилятор tsc намного более снисходительный, чем VS2017, вероятно, потому, что VS2017 сканирует код (включая символическую ссылку node_modules ), чтобы обеспечить хороший intellisense, и, таким образом, запутывается. Однако у меня есть большие сложные проекты с несколькими npm-модулями, поэтому используйте VS2017 ... поэтому прочитайте варианты 2 и 3, если у вас есть аналогичные потребности ....

вариант 2: выпустить d.ts

если вы используете outDir и rootDir (в вашем tsconfig.json ), ваш lib-модуль с символической ссылкой должен выдавать объявления d.ts и эти объявления должны быть в lib-модуле package.json types свойство.

вот пример того, как должен выглядеть tsconfig.json вашего 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"
  ]
}

и ваш lib-модуль package.json должен включать что-то вроде следующего:

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

Этот вариант работает хорошо, основная проблема заключается в том, что в Visual Studio при отладке или «перейти к определению» или «показать все ссылки» он покажет вам d.ts не фактические исходные файлы машинописного текста, что побеждает главное преимущество визуальной студии (навигация в больших проектах)

если вы хотите увидеть реальный пример этого в дикой природе, посмотрите модуль npm xlib v8.5.x

вариант 3: отправить .js строку с исходным кодом (мой любимый выбор)

Вы можете использовать свои файлы .ts напрямую для ввода символьных lib-модулей! но только если вы не используете файл outDir`` and rootDir in your tsconfig.json```. Это позволит ссылкам на VS2017 работать правильно. Вот необходимые вам настройки конфигурации:

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

и package.json вашего lib-модуля следует изменить на:

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

предостережения (вещи, которые не работают с вариантом 3)

Вышеупомянутые обходные пути работают только в том случае, если каждый модуль lib НЕ генерирует избыточную информацию о типе. Например, у меня была библиотека xlib выставляла определения типа @types/async . Но затем у меня была другая библиотека, которая также независимо ссылалась на @types/async . Использование файлов .ts напрямую для ввода приводит к тому, что tsc импортирует async из двух модулей lib, что приводит к возникновению различных форм ошибок duplicate identifier . чтобы решить эту проблему, вам нужно либо не импортировать один и тот же @types из нескольких lib-модулей, либо использовать вариант 2 .d.ts обходной путь

резюме

Надеюсь, это сэкономит вам часы, на которые я потратил ... В целом это очень болезненно, и я надеюсь, что команда машинописных текстов сможет исправить модули с символическими ссылками. Но, по крайней мере, сейчас это работает (до 2.x это было практически невозможно)

Обходной путь, опубликованный @mhegazy в https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001 (вариант обходного пути 2 @jasonswearingen), решил эту проблему при использовании связанных модулей в проекте lerna!

Я просто подумал, что поделюсь своим опытом ... пытаясь создать / извлечь библиотеку из существующего проекта, чтобы ее можно было использовать в других проектах.

Windows 10 Корпоративная
VS 2015, обновление 3
Инструменты для VS2015 2.2.2
Код VS 1.12.2
Машинопись 2.2.2
NPM: 3.10.9
Узел: 6.9.2

У нас есть проект VS 2015 ASP.MVC с интерфейсом Angular 4.1.x, из которого мы начали извлекать некоторые компоненты, чтобы создать общую библиотеку, чтобы их можно было использовать в других проектах.

Проект библиотеки построен с использованием VS Code и использует накопительный пакет для сборки версий es2015, es5 и umd в папке dist вместе с соответствующими файлами d.ts.

Конечный результат выглядит примерно так:

-- 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 связал папку dist / mylib с папкой с моим проектом VS 2015 / Angular 4.1.x.

Когда я пытаюсь скомпилировать проект в VS 2015, я получаю сообщения того же типа, которые описаны в некоторых из приведенных выше ситуаций для подписки, наблюдаемого и т. Д.

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

Если я временно удаляю каталог node_modules из проекта библиотеки, я получаю новые ошибки с жалобами на невозможность поиска модулей:

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

Это приводит меня к выводу, что когда компилятор машинописного текста компилирует приложение, он действительно ищет в папке node_modules моего пакета связанной библиотеки определения модулей для моей библиотеки, а не в папке приложений node_modules.

Мне неясно, какое из предложенных выше решений предоставит обходной путь для этой проблемы, может ли кто-нибудь помочь мне?

Благодаря!

@mikehutter В вашем проекте, который использует вашу библиотеку (а не в самой библиотеке), сделайте что-то вроде этого в вашем tsconfig:

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

Вам может потребоваться небольшая корректировка в зависимости от того, где находится ваш tsconfig и исходный код.

(Как и другие участники этой ветки, я бы хотел увидеть некоторые улучшения TypeScript, которые делают это ненужным.)

@mikehutter мы недавно добавили некоторые рекомендации в Angular CLI для работы со связанными библиотеками, и похоже, что в вашем случае вам не хватает конфигурации путей TypeScript для RxJ в вашем потребительском приложении. См. Https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/linked-library.md для получения дополнительной информации.

@kylecordes на высоте 👍

Спасибо @kylecordes и @filipesilva! Это все, что мне нужно ...

Привет!

@mhegazy , вы верите, что это дойдет до 2,4 или, скорее всего, снова
Это действительно болезненно, чтобы обойти это, вынуждая каждый проект всегда определять сопоставления путей для вещей, о которых они действительно не должны заботиться.

Очень надеюсь, что на этот раз это попадет в релиз!

Лучший,

Не думаю, что об этом еще упоминалось, но супер-сокращенный способ решения этой проблемы:

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

Запись paths выше в основном говорит: для любого модуля сначала найдите его в папке node_modules в корне проекта, затем вернитесь к обычному правилу (рекурсивный переход по каталогам, откуда импорт произошел).

(Пожалуйста, поправьте меня, если я ошибаюсь, я все еще относительный новичок в TS).

Запись в paths кажется относительной к baseUrl . Итак, если вы установили baseUrl как вложенную папку, вам необходимо соответствующим образом изменить определение путей. Например:

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

@fiznool fyi, это часть моих вариантов обхода 2 и 3 (в моем сообщении выше). Я видел, что простой установки свойства paths недостаточно, если у вас есть проекты с символическими ссылками, использующие те же типы.

@jasonswearingen ваш пост намного более подробный, чем мой ... спасибо, что прояснили это. Я обязательно вернусь к нему, если у меня возникнут другие проблемы. 😄

Мы видим это и в проектах Google. Как описано здесь:
https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -306969543

Описанные выше обходные пути с использованием baseUrl и путей, похоже, не работают, tsc по-прежнему выбирает повторяющиеся определения и никакой комбинации путей / baseUrl / include / exclude / и т. Д. смог убедить его в обратном.

Мне любопытно, как это работает нормально, если у вас есть проект, который зависит от X, а также зависит от Y, который транзитивно зависит от X, как tsc избегает загрузки определений типов дважды?

@esprehn Я настоятельно рекомендую вам прочитать мой пост об обходном пути здесь: https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -302886203

Что касается этой ссылки, оба моих решения (2 и 3) требуют большего, чем просто установка baseUrl и путей, поэтому, если это все, что вы делаете, пожалуйста, перечитайте. «легкий» способ - это решение 2, но я предпочитаю решение 3, поскольку оно позволяет правильно «перейти к определению» через визуальную студию. проблема с решением 3 заключается в том, что вам нужно только один раз загружать внешние определения .d.ts в цепочку зависимостей.

надеюсь, это поможет.

+1 Я использую lerna, и подзависимость с включенными типами помечается как "дубликат" при включении через связанные зависимости.

Если нужно, могу поделиться кодом.

В WebPack, как в Angular-CLI, пусть этот Angular-CLI package.json ссылается на пакет RXJS , затем удалите пакет RXJS из любого другого проекта package.json, который вам не нужен из-за WebPack .

Эта ситуация может произойти не только с символическими ссылками, но и с npm-shrinkwrap.json в зависимости от @types/node в dependencies . Shrinkwrap заставляет npm установить две идентичные версии @types/node в родительский пакет и в упакованный в shrinkwrap. См. Https://github.com/KingHenne/custom-tslint-formatters/issues/5.

Также сталкивался с этим при использовании проекта реакции, в котором установлен @types/react и связывания его с приложением, которое также использует @types/react

У меня была такая же проблема при работе с пакетами yarn link -ed.
Rx.js выдает ошибку: 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>'

К счастью, я решил эту проблему, используя ту же версию Rxj.s в родительских и связанных пакетах.
Итак, в моем случае две разные версии Rx.js вызвали проблему.

Это огромный блокиратор при работе с монорепозиториями. Очень надеюсь, что это больше не будет откладываться и попадет в 2.5.

Изменить: 😮

image

Интересно. Monorepo - это единственный сценарий, в котором моя команда НЕ сталкивается с этой проблемой, потому что символические ссылки указывают все обратно в общую папку пакета.

Моя команда довольно часто сталкивается с этой проблемой при компоновке наших собственных внутренних библиотек во время разработки.

Недавно мы нашли инструмент под названием yalc, который очень хорошо смягчает это и фактически создает довольно хороший цикл разработки. (В качестве tl; dr вместо связывания всего пакета он запускает сценарии предварительной публикации и копирует результат в связанную папку).

Эта проблема, кажется, постоянно отодвигается. Поскольку это действительно нарушает рабочие процессы очень многих людей, можем ли мы потенциально иметь какое-то временное решение, такое как «отключить комментарий», как предложено в # 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$);

«Отключить комментарий» не намного лучше, чем простое приведение типов везде, что довольно болезненно в большом проекте. Выше я предлагал следующее изменение компилятора:

Если ВСЕ эти условия верны, НЕ сообщайте TS2345 для классов с закрытыми членами:

  1. Публичные подписи совместимы в соответствии с обычной утиной типизацией TypeScript.
  2. Классы определены в папках пакетов NPM с тем же именем и версией (согласно package.json).
  3. Классы имеют одинаковый относительный путь для своего модуля (например, "./lib/blah/Bdts")

Если какой-либо из этих критериев не выполняется, можно сообщить о TS2345.

Упрощенное исправление также будет лучше, чем текущая ситуация, например, рассмотрите только №1, возможно, только если люди подпишутся через tsconfig. Это должно быть довольно дешево в реализации.

Преимущество этого подхода состоит в том, что он просто отключает ложные срабатывания сигнализации, но сохраняет существующую семантику. В то время как хаки переназначения node_modules изменяют разрешение модуля NPM потенциально неправильным образом (например, вызывая сбой кода в приведенном мной гипотетическом примере ).

Честно говоря, я даже не уверен, нужно ли это «исправлять» в Typescript, поскольку есть проблема с простым JavaScript: оператор instanceof вернет false, если класс объекта отличается от предоставленного класса.

Таким образом, я бы с нетерпением ждал лучшей альтернативы ссылке npm, которая, возможно, сначала подключается к require ().

Это хорошее понимание. Вы смотрели pnpm ? Это небольшой шаг вперед по сравнению с текущим дизайном node_modules, но очень эффективный, если я правильно его понимаю.

Речь идет не только о npm link который можно заменить или не использовать, но о наличии нескольких версий одного и того же пакета @types/xxx , установленных одновременно, часто извлекаемых из зависимостей, которые предоставляют объявления TypeScript, которые зависят от по стандартным декларациям, как я и другие сообщали. Количество таких пакетов будет расти по мере более широкого принятия TypeScript в сообществе Node.

@Yogu Я думаю, это сбивает с толку идентичность и равенство. Несмотря на то, что импорт одного и того же пакета / версии из двух мест может представлять два разных экземпляра типа, они все равно равны по типу.

На ум приходит следующий (действительный) код:

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

function foo (bar: a) {}

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

То же самое относится и к импортируемым нами библиотекам.

Типы, импортированные из разных версий библиотек (и соответствующих пакетов @types ), могут быть как равными, так и разными (если библиотека обновляется, определение типа также должно обновиться, чтобы отразить изменения).

Я только что объединил изменение, которое попытается обнаружить повторяющиеся пакеты на основе их имени и версии и использовать только один. Пожалуйста, попробуйте его, используя typescript@next когда он будет опубликован в следующий раз.

Ура, спасибо за то, что исправили это! :-)

@pgonzal Спасибо за указатель на pnpm, это определенно выглядит интересно!

@sompylasar @types/node - это немного особый случай, но для @types/react вот мое предложение: поместите все зависимости, необходимые для API модуля, в peerDependencies , не в dependencies . Это дает понять, что версии зависимостей должны совпадать (или, по крайней мере, быть совместимыми) между родительским и дочерним модулями. Если родительский и дочерний оба используют react, но не обмениваются объектами типа react, эта проблема здесь вообще не возникает.

@harangue Если класс объявлен дважды в двух разных файлах, с одним и тем же именем и одинаковой структурой, остаются два разных класса, которые не считаются равными в JavaScript. Как я уже упоминал, оператор instanceof прежнему будет различать экземпляры двух классов.

См. Эту скрипку для демонстрации.

По этой причине я бы предпочел решить эту проблему на уровне NPM (так что у нас в первую очередь нет нескольких объявлений, если это не предусмотрено), чем в TypeScript.

@Yogu : +1: поэтому, если @types/node - это особый случай, то есть вы не можете выполнять программу, используя две разные версии узла одновременно, это будет одна версия, и, скорее всего, та, которая указана в пакет верхнего уровня, возможно, TypeScript следует рассматривать его как особый случай, например, всегда использовать @types/node верхнего уровня для каждой зависимости?

@ andy-ms Спасибо за это!

Пожалуйста, попробуйте это, используя typescript @ next, когда он будет опубликован в следующий раз.

Полагаю, этого еще не произошло. Я пробовал это с парой проектов, но пока безуспешно. Было бы здорово увидеть обновление в этой теме, как только появится next . @ Энди-мс

Похоже, ежедневные сборки снова остановились. Последним было: 2.5.0-dev.20170808 .

cc / @DanielRosenwasser

Я не уверен, связано ли это, но при попытке 2.5.1 я, кажется, вижу только один аспект модуля, даже если он расширяет d.ts где-то еще.

если у меня есть @types для чего-то, скажем, @types/mongodb и у меня есть пользовательское объявление, которое расширяет этот модуль, то есть добавляет обещание к методам, поэтому теперь у меня есть @types/mongodb который имеет модуль mongodb и у меня есть файл d.ts в моем проекте, называемый чем-то вроде mongo-promisification.d.ts который содержит модуль mongodb .

Итак, в этом сценарии выше у меня есть файл с import {somethingFromTypes} from "mongodb" он жалуется, что данные из модуля типов не могут быть найдены, даже если они там и действительны, но если бы я сделал import {somethingFromMyExtendingDts} from "mongodb" который работает хорошо.

При компиляции мне просто говорят, что модуль не экспортирует этот материал, когда он это делает, так что это желаемое поведение, и мне просто нужно повторно экспортировать мой собственный d.ts или он должен принимать как типы, так и расширение d.ts Я имею?

Я использую последнюю тестовую сборку (64-разрядная версия Windows 10), и мне кажется, что это не исправлено.

Размножение

Структура

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

Бежать

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

a / index.ts

import { Observable } from 'rxjs/Observable';

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

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

Бежать

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 Я думаю, что проблема в вашей ситуации заключается в том, что у вас есть два объявления модуля, где вам нужен модуль и дополнение.
Вы должны сделать mongo-promisification.d.ts вот так:

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

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

Без import вы находитесь в окружающем контексте и пишете новое объявление, а не дополнение.

( Справочник )

Могу подтвердить, что теперь это работает для меня с помощью [email protected] . Большое спасибо @andy-ms - это меняет правила игры!

У меня была такая же проблема, когда я импортировал Observableчерез библиотеку Typescript в проект angular-cli, и функции использовали фрагмент кода

Функция getitems (): Наблюдаемый
http.get (). map (response: Response) => {
возвращениеresponse.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 Мне нужен полный пример, чтобы воспроизвести вашу ошибку. Кроме того, убедитесь, что вы используете typescript@next - angular-cli может иметь более старую версию, в которой нет функции дедупликации.

Я пробовал [email protected], но все равно получаю много ошибок TS2300: повторяющийся идентификатор.
К сожалению, я не могу поделиться проектом целиком. Но вот некоторые подробности:
tsconfig пакета 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 основного проекта ( @croc/webclient - связанный пакет):

    "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, можете ли вы сократить свой проект до простого примера, демонстрирующего проблему?

@mhegazy вот это
https://github.com/evil-shrike/typescript-npmlink-issue
в корне проекта:

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

затем в main :

npm run tsc

Привет, @ evil-shrike, я сузил проблему до:
lib / tsconfig.json

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

основной / tsconfig.json

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

Итак, мы включаем оба (от tsc --listFiles ):

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

Поскольку node_modules происходит от include а не от разрешения модуля, я не думаю, что мы вызываем для него realpath , поэтому в итоге получается два разных включаемых файла.
Лучше все равно не включать ваши node_modules , а вместо этого скомпилировать их отдельно и импортировать так же, как любой другой внешний пакет.

@ Энди-мс
Сделать это непросто. Ссылочная библиотека в моем случае имеет множество окружающих d.ts, которые, например, расширяют глобальные интерфейсы. Как JQueryStatic:

interface JQueryStatic {
    cleanData (elems);
}

или объявить префиксы для загруженных (requirejs):

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

Затем где-то в исходном коде библиотеки он их использует:

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

Когда такой модуль (из библиотеки) будет импортирован где-то в основном, он не будет компилироваться.

В исходном коде вашей библиотеки вы должны использовать директивы /// <reference types="" /> (или /// <reference path="" /> ), чтобы гарантировать наличие необходимых типов при импорте вашей библиотеки. Таким образом, это не обязательно должно быть в "include"; когда он будет импортирован, ссылочные типы будут автоматически добавлены в проект.

@ andy-ms спасибо, я реорганизовал свою библиотеку, и теперь проект, в котором она npm-link-ed, компилируется нормально.

Не уверен, что это слишком большие репродукции, но я получаю то же самое от базовой установки CLI с angular @ next и typescript @ next для работы с Observable<T> !== Observable<T> :

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

Синий импортирует и использует компоненты и услуги из Red

@intellix Не могли бы вы получить пример ошибки, использующей только командную строку tsc ? Трудно сказать, какая версия машинописного текста используется ng .

@ andy-ms У меня все еще проблема. Это происходит у меня при попытке использовать npm-ссылку между любыми расширениями vscode я создаю. Все они импортируют vscode что вызывает повторяющиеся ошибки идентификатора.
TS Version 2.7.0-dev.20171118

Для меня это сработало, например, карту «rxjs / *» в конкретную папку rxjs в node_modules в разделе путей файла tsconfig.
Теперь все нормально работает со ссылкой npm.

Я также видел, как это происходило при переходе от символьной ссылки к несимвольной от ссылки обновления версии на пакет.

См. Также этот вопрос SO: https://stackoverflow.com/questions/38168581/observablet-is-not-a-class-deved-from-observablet

@dakaraphi @JoshuaKGoldberg Не могли бы вы дать инструкции по воспроизведению этих сценариев?

С новым поведением мы не должны включать пакет, если мы уже видели другой пакет с таким же значением «версия» в его package.json . Если у вас несколько установок с разными версиями, вы получите две разные копии модуля. Это могло бы объяснить, почему обновление версии нарушило бы это, если бы оно затронуло только одну из двух установок.

@ andy-ms У меня есть следующие репозитории:

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

Я использую локальную установку npm для ссылки на vscode-extension-common из vscode-extension-fold

Если вы проверите эти репозитории, они в настоящее время работают, потому что у меня есть обходной путь сопоставления путей в package.json vscode-extension-fold . Однако, если я правильно понимаю, мне не нужно это обходное решение.

@dakaraphi Спасибо! Похоже, что ошибка связана с тем, что vscode.d.ts написано как глобальное внешнее объявление, а не как внешний модуль. Я создал Microsoft / vscode-extension-vscode # 90.

Это все еще не работает для меня, когда я пытаюсь связать 2 пакета, каждый из которых зависит от rxjs . Я использую [email protected] и [email protected] . Оба пакета используют одну и ту же версию. Есть ли у кого-нибудь обходной путь?

@SamVerschueren Не могли бы вы дать конкретные инструкции по воспроизведению ошибки? Также проверьте с помощью typescript@next .

@ andy-ms Я посмотрю, что я могу сделать!

@ andy-ms Вот небольшой репозиторий репродукций https://github.com/SamVerschueren/ts-link-6496. Я использовал [email protected] чтобы воспроизвести это.

  1. Установите обе зависимости для mod-a и mod-b
  2. Скомпилируйте mod-b с yarn build
  3. Скомпилируйте mod-a с yarn build

Шаг 3 завершится ошибкой со следующей ошибкой

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.

Все еще сталкиваюсь с этой проблемой с [email protected]. Также попробовал typescript @ next и имел ту же проблему.

Похоже, что корень проблемы в том, что связанные пакеты по-прежнему ссылаются на определения типов в своих собственных локальных node_modules а не на типизацию из node_modules с которой они связаны, когда это возможно. Это в сочетании с тем, что:

  1. глобальные переменные не могут быть переопределены

    • это заставляет компилятор жаловаться, когда глобальное значение определено как в родительском проекте node_modules так и в node_modules в связанном пакете

  2. классы, которые в остальном идентичны, не могут быть присвоены друг другу

    • это заставляет компилятор жаловаться при попытке назначить переменную, тип которой является классом из родительского проекта node_modules значению, возвращаемому связанным пакетом, тип которого определен в его собственном node_modules

Мне удалось обойти эту проблему с помощью переменной paths config. Для модулей, определения которых взяты из @types/* , как предлагается здесь , вы можете просто использовать:

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

В случае, если вы столкнетесь с этой проблемой с пакетом, который поставляется в комплекте с определениями типов, которые определяют классы или глобальные объекты, вам придется добавить их вручную. Например, rxjs :

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

У меня также возникают проблемы с символическими ссылками, когда я добавляю локальный пакет, используя TS 2.8.3:

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

Начиная с версии 3, npm, по-видимому, устанавливает их с символическими ссылками вместо копирования файлов.

Однако, когда я пытаюсь скомпилировать, компилятор видит связанный файл определения как два отдельных и конфликтующих файла:

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

Если вместо этого я скопирую файлы вручную, все будет работать должным образом. Я могу обойти это, установив typeRoots: ["./node_modules/**/"]

Была ли эта страница полезной?
0 / 5 - 0 рейтинги