Как правильно запрашивать типы из зависимостей в машинописи? - PullRequest
0 голосов
/ 03 февраля 2019

У меня есть вопрос относительно разрешения типов в моем проекте.Таким образом, в основном у меня есть packageA -> packageB-v1 -> packageC-v1, и я хотел бы использовать тип, объявленный в packageC-v1 в packageA.

Все пакеты созданы мной, и все они являются пакетами машинописи, которые генерируют файлы объявленийУстанавливая declaration: true в tsconfig.json файле, каждый из них предоставляет несколько *.d.ts файлов в своей папке dist.Для типов нет соответствующего пакета @types/*.

В этом случае как правильно импортировать типы?До сих пор я пробовал:

  1. import SomeType from 'packageB-v1/node_modules/packageC-v1/dist/SomeType'.Это работает, но мне не нравится, что packageA нужно знать, где установлен packageC, поскольку это может измениться, зависит от инструмента управления пакетами (npm / yarn) или от порядков установки (см. https://medium.com/learnwithrahul/understanding-npm-dependency-resolution-84a24180901b). IБыли проблемы, связанные с тем, что из-за разных версий packageC типы не совпадают, и tsc не подходит для этого. Это может произойти, когда есть другая зависимость, такая как packageA -> packageB-v1 -> packageBB-v1 -> packageC-v2, где npm установит packageC-v2вместо packageC-v1 в packageB/node_modules.
  2. Сначала экспортируйте необходимые типы SomeType из packageB-v1 на export SomeType from 'packageC-v1', затем из пакета А я могу import SomeType from 'packageB-v1'. Это тоже работает, однако это тожеозначает, что packageB-v1 готов к повторному экспорту всех типов из всех его зависимостей (их может быть много), которые могут потребоваться его потребителям Обычно это невозможно. Кроме того, я слышал, что реэкспорт может генерировать разные типы в зависимости от каждого случая.
  3. В package.json файле packageA явно добавьте зависимость к packageC-v1даже на самом деле это напрямую не зависит от него, поэтому мы можем использовать import SomeType from 'packageC-v1/SomeType. Uк сожалению, это тоже не сработает, так как у нас может быть другая цепочка зависимостей, такая как packageA -> packageD-v1 -> packageC-v2.В таком случае, какую packageC версию мы должны установить под packageA?Этот подход также плох, потому что даже несмотря на то, что машинопись не будет включать packageC в сгенерированный JS-пакет из packageA только для использования интерфейсов, она может сделать это для перечислений.

Последний способ, которым яЯ не пытался создать свой собственный @types/packageC-v1 и опубликовать его (и другие мои пакеты TS).Однако, если я пишу эти пакеты для частной организации, это означает, что нам необходимо поддерживать внутренний репозиторий типов, а также поддерживать парные версии пакетов и ассоциированные с ними типы.Даже если мне удастся сделать это, я все еще вижу много проблем с этим подходом с точки зрения несоответствия версий, конфликта глобальных объявлений или конфликта имен (это также верно в подходе DefinetelyTyped/types).

IЯ не уверен, имеют ли они смысл для вас, и действительно нуждаются в некоторых советах здесь.

1 Ответ

0 голосов
/ 03 февраля 2019

Давайте начнем с тривиальности: если пакет A нуждается в чем-то из пакета C, то C по определению является прямой зависимостью A.

Вы говорите, что у вас есть причиначтобы не включать C в зависимости A

, у нас может быть другая цепочка зависимостей, например packageA -> packageD-v1 -> packageC-v2

В этомВ случае, если A использует типы из C-v1, как это должно работать?Я вижу только две возможности:

  1. A не требует типов от C при использовании packageD.(кстати, зачем тогда нужны C типы для использования packageB?)

  2. C типы не изменились, поэтому C типы от C-v1совместимы с C-v2

Единственное решение, которое я вижу как для № 1, так и для № 2, - это разделение типов из C на отдельные пакеты, например C-types,и сделайте его зависимостью от A.

Типы в C-types должны , а не быть d.ts файлами, сгенерированными TypeScript, это должны быть все интерфейсы, типы и перечисления (но не классы, классы - это детали реализациии должен оставаться в C) из C, перемещаться в обычный файл .ts, включенный в отдельный пакет.

Вам нужно будет опубликовать C-types в репозитории npm так же, как C публикуется с сгенерированными .d.ts и пустыми .js файлами для каждой версии C.Я не думаю, что наличие пустых .js файлов является проблемой, но если это так, вы можете просто опубликовать вручную написанные .d.ts файлы (однако я не знаю, чтобы проверить их перед публикацией, не используя другой пакет, использующийих).Нет необходимости публиковать C-types - DefinitiveTyped и помещать их в область действия @types - это просто соглашение, а не требование.Вы просто должны сказать всем в вашей организации использовать C-types вместо @types/C.

Вы говорите, что с этим подходом

Я все еще вижу много проблем с этим подходомс точки зрения несоответствия версий, конфликта глобальных объявлений или конфликтов имен (это также верно в подходе DefinetelyTyped / types)

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

И если ваш A использует типы из C, у вас будут точно такие же проблемы с версиями для разных версий C.Разделение типов из C просто заставит вас задуматься об этих проблемах заранее, вместо того, чтобы надеяться, что все будет «просто работать».

...