Typescript: Рассмотрите возможность доступа к глобальным объектам UMD из модулей

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

По отзывам № 7125, некоторые люди действительно смешивают и сопоставляют глобальные и импортированные библиотеки UMD, что мы не рассматривали как вероятный сценарий при реализации этой функции.

Три возможных варианта:

  1. Делайте то, что мы делаем сегодня - плохо, потому что нет хорошего обходного пути
  2. Разрешите некоторый синтаксис или конфигурацию, чтобы сказать «этот глобальный UMD действительно доступен глобально» - несколько сложно, но выполнимо
  3. Разрешить доступ ко всем глобальным UMD независимо от контекста - пропускает ошибки, когда люди забывают импортировать глобальные UMD в файл. Предположительно они встречаются довольно редко, но было бы глупо их пропустить.

Похоже, это сработает, но, вероятно, не будет:

  1. Пометить импортированные модули UMD как «недоступные для глобальных» - плохо, потому что модули UMD будут импортированы в файлы объявлений во время расширения модуля. Было бы странно иметь разное поведение импорта из файлов реализации и файлов декларации.

Я склоняюсь к варианту 3 для простоты, но могу увидеть вариант 2, если есть какой-нибудь достаточно хороший синтаксис или конфигурация, которые мы могли бы использовать в логическом месте. Обнаружить использование глобального UMD в правиле TSLint было бы просто, если бы кто-то захотел это сделать.

Один путь вперед - реализовать вариант 3, и если окажется, что люди часто делают ошибку «забыл импортировать», добавьте параметр tsconfig globals: [] который явно указывает, какие глобальные объекты UMD разрешены.

Add a Flag Committed Suggestion good first issue help wanted

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

+1 по этому поводу. Я просто пытался использовать React с SystemJS, и поскольку React не очень хорошо сочетается, я просто загружаю его прямо из CDN в теге скрипта, и, таким образом, объекты React / ReactDOM доступны во всем мире.

Я пишу код в виде модулей в качестве лучшей практики, но он будет объединен (Rollup) в один сценарий времени выполнения, который выполняется при загрузке. Больно (и ложно) иметь import from react / react-dom, а затем настроить загрузчик так, чтобы он говорил «не совсем, это глобальные объекты» (аналогично примеру конфигурации WebPack, указанной в https: / /www.typescriptlang.org/docs/handbook/react-&-webpack.html). Было бы намного проще (и точнее) сделать их доступными в моих модулях как глобальные. Шаги, которые я попробовал, поскольку они казались интуитивно понятными, были следующими:

  1. npm install --save-dev @types/react @types/react-dom
  2. В моем tsconfig.json: "jsx": "react", "types": ["react", "react-dom"]
  3. В моем модуле: export function MyComponent() { return <div>{"Hello, world"}</div>; }
  4. Аналогично: ReactDOM.render(...)

Однако это приводит к ошибке React refers to a UMD global, but the current file is a module. Consider adding an import instead .

Если бы это сработало, это было бы намного проще, чем притвориться в коде модулем, а затем настроить загрузчик / сборщик, что это не так. (Или, в качестве альтернативы, я сделал то, что ожидал, добавив файл, содержащий нижеприведенный. Теперь мои модули могут использовать React и ReactDOM как глобальные объекты без ошибок, но это некрасиво / хакерско - хотя может быть более простой способ. пропустил):

import * as ReactObj from "react";
import * as ReactDOMObj from "react-dom";

declare global {
    var React: typeof ReactObj;
    var ReactDOM: typeof ReactDOMObj;
}

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

Вместо того, чтобы разрешать доступ ко всем глобальным объектам UMD независимо от контекста, не было бы проще разрешить доступ только к глобальным объектам UMD, если на модуль UMD явно "ссылаются" (не импортированы) с помощью синтаксиса ///<reference types=<>> , или через конфигурацию types в tsconfig.json?

Другими словами, почему бы просто не разрешить использование ///<reference types=<>> в модуле?

Если мы сказали, что /// <reference type="x" /> означало, что x был глобально доступен _everywhere_, часто случается так, что какой-то файл .d.ts где-то будет неправильно ссылаться на вещи, которые не являются действительно глобальными ( Я могу сказать вам это, потому что я поддерживал ветвь 2.0 Определенного Типа, и это чрезвычайно распространенная ошибка).

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

Понимаю. Что ж, если это ни на кого не влияет, возможно, лучше сохранить текущее поведение. Мне просто нужно полностью перейти к импорту вещей в виде модулей.

Изменить: рад видеть, что это влияет на многих людей, кроме меня.

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

Я использую lodash, который не имеет собственной типизации. У меня также есть ситуация, когда в моей среде выполнения проще всего использовать операторы импорта относительного пути. Итак, у меня есть комбинация операторов импорта с локальными относительными путями и родственниками папок ('./foo', а также 'N / bar').

Если я вручную скопирую @types/lodash/index.d.ts в node_modules/lodash/ я могу получить данные для проверки типов.

До сих пор мой обходной путь использовал ///<amd-dependency path='../lodash' name="_"> (а не import ). С этой комбинацией определения @ types / lodash будут видны компилятору «глобально» и по-прежнему будут иметь правильный относительный путь ( ../lodash ) в сгенерированном JS.

Надеюсь, этот сценарий достаточно близок к этой проблеме?

Вы можете уточнить

У меня также есть ситуация, когда в моей среде выполнения проще всего использовать операторы импорта относительного пути.

и

Если я вручную скопирую @types/lodash/index.d.ts в node_modules/lodash/ я могу получить данные для проверки типов.

пожалуйста? Я не знаком с этим сценарием, так какова его цель и почему он полезен?

Привет, ребята,

Я нахожусь в процессе поиска решения текущих @types/bluebird декларации проблемы (пожалуйста , не тратить время на чтение его). Я обнаружил, что проблему можно решить, добавив export as namespace Promise; в .d.ts, но затем я столкнулся с проблемой, описанной в этой проблеме с github.

Короче, хотелось бы, чтобы работало следующее:

  1. git clone -b vanilla-es5-umd-restriction-problem https://github.com/d-ph/typescript-bluebird-as-global-promise.git
  2. cd typescript-bluebird-as-global-promise
  3. npm install
  4. Отредактируйте node_modules/@types/bluebird/index.d.ts , добавив export as namespace Promise; над строкой export = Bluebird; .
  5. npm run tsc

Текущий результат:
Пара ошибок 'Promise' refers to a UMD global, but the current file is a module. Consider adding an import instead. .

Ожидаемый результат:
Компиляция прошла успешно.

Эта проблема особенно сложна, потому что она вызвана использованием Promise как в коде разработчика, так и в стороннем коде (в этом случае RxJS). Последнее предполагает, что Promise является глобальным (предоставляется стандартом JS), поэтому никогда не изменится на использование, например, import Promise from std; // (not that "std" is a thing) .

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

Благодарю.

----------------------------- Обновить

В итоге я решил эту проблему по-другому (а именно: путем расширения интерфейсов Promise и PromiseConstructor ).

Параметр "globals": [] tsconfig кажется предпочтительнее, чем делать их видимыми везде. Поскольку декларация UMD становится нормой, вероятность случайно забыть импортировать модуль высока. Пожалуйста, рассмотрите возможность сохранения текущего поведения. Это должно быть ошибкой.

Как ни странно, я помню, как момент удалил их глобальную переменную window.moment в момент выпуска. Мы думали, что разумно ввозили его повсюду, но забыли про 5 мест.

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

+1 по этому поводу. Я просто пытался использовать React с SystemJS, и поскольку React не очень хорошо сочетается, я просто загружаю его прямо из CDN в теге скрипта, и, таким образом, объекты React / ReactDOM доступны во всем мире.

Я пишу код в виде модулей в качестве лучшей практики, но он будет объединен (Rollup) в один сценарий времени выполнения, который выполняется при загрузке. Больно (и ложно) иметь import from react / react-dom, а затем настроить загрузчик так, чтобы он говорил «не совсем, это глобальные объекты» (аналогично примеру конфигурации WebPack, указанной в https: / /www.typescriptlang.org/docs/handbook/react-&-webpack.html). Было бы намного проще (и точнее) сделать их доступными в моих модулях как глобальные. Шаги, которые я попробовал, поскольку они казались интуитивно понятными, были следующими:

  1. npm install --save-dev @types/react @types/react-dom
  2. В моем tsconfig.json: "jsx": "react", "types": ["react", "react-dom"]
  3. В моем модуле: export function MyComponent() { return <div>{"Hello, world"}</div>; }
  4. Аналогично: ReactDOM.render(...)

Однако это приводит к ошибке React refers to a UMD global, but the current file is a module. Consider adding an import instead .

Если бы это сработало, это было бы намного проще, чем притвориться в коде модулем, а затем настроить загрузчик / сборщик, что это не так. (Или, в качестве альтернативы, я сделал то, что ожидал, добавив файл, содержащий нижеприведенный. Теперь мои модули могут использовать React и ReactDOM как глобальные объекты без ошибок, но это некрасиво / хакерско - хотя может быть более простой способ. пропустил):

import * as ReactObj from "react";
import * as ReactDOMObj from "react-dom";

declare global {
    var React: typeof ReactObj;
    var ReactDOM: typeof ReactDOMObj;
}

Я также согласен с тремя вариантами плюс глобальные: [] резервное копирование. Это кажется довольно интуитивно понятным для новых и старых пользователей и дает именно ту функциональность, которая им нужна.

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

Если бы я хотел получить помощь в реализации любого из них, куда мне обратиться?

Это действительно должно быть за флагом. Это серьезная опасность рефакторинга. Даже если по умолчанию установлен флаг true. Я думаю, что это должно продолжать работать в исходном сценарии, иначе мы потеряем основное преимущество объявлений UMD.

React не очень хорошо связывается

@billti можешь уточнить?

Больно (и ложно) иметь import from react / react-dom, а затем настроить загрузчик так, чтобы он говорил "не совсем, это глобальные объекты".

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

См. Эту проблему (https://github.com/rollup/rollup/issues/855), чтобы увидеть один из примеров того, как они пытаются оптимизировать объединение и наблюдаемые размеры. Фактически в моей настройке (с использованием Rollup) я увидел минимальный выигрыш в размере от React, поэтому я бы предпочел просто обслуживать его из CDN. Для меня это имеет следующие преимущества:

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

Заглянув в инструменты разработчика Chrome при загрузке сайта, React и React-dom (минимизированные версии) при HTTP-соединении с GZipped составляют всего 47 КБ сетевого трафика, что меньше, чем у большинства изображений на сайте, поэтому я не в любом случае беспокоится о попытках сократить это количество, если только не будет действительно большой выгоды (например, 50% -ное сокращение).

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

@billti SystemJS полностью поддерживает этот сценарий. Вы можете переключаться между использованием локально установленного пакета во время разработки и использованием CDN в производственной среде. Он также имеет полную поддержку метаданных, которые указывают, что весь импорт должен фактически указывать ссылки на глобальную переменную, которая будет извлечена один раз и прикреплена к объекту окна при первой необходимости, в производстве это может поступать из CDN. Я не делал этого с помощью реакции, но я сделал это с помощью angular 1.x

Спасибо @aluanhaddad . Интересно ... Я на самом деле пытался заставить что-то подобное работать, что привело меня к этому препятствию, и не мог понять этого, поэтому сегодня утром задал вопрос о репозитории SystemJS. Если вы можете ответить, как достичь https://github.com/systemjs/systemjs/issues/1510, это будет действительно полезно :-)

Примечание.Мой другой комментарий по-прежнему остается в силе, что испускание самого TypeScript невозможно без этого, так как вам нужно что-то вроде SystemJS / WebPack / Rollup и т.д ... для сопоставления импорта с глобальными объектами для запуска кода.

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

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

К вашему сведению: я получил эту работу в SystemJS с помощью SystemJS API и добавил свое решение на https://github.com/systemjs/systemjs/issues/1510 . Благодарю.

По второму пункту: да, я знаю, что именно это могут делать загрузчики. Я хочу сказать, что они могут сопоставить импортированный модуль с глобальным, но TypeScript не может - поэтому вам нужно использовать загрузчик, чтобы сделать ваш код действительным во время выполнения. Итак, это уловка-22 с этой исходной проблемой, когда вы не можете объявить, что глобальный (в данном случае React) доступен в модуле, вы должны импортировать его, как если бы это был модуль (а это не так) .

Мой другой комментарий по-прежнему остается в силе, что испускание самого TypeScript не может использоваться без этого, поскольку вам нужно что-то вроде SystemJS / WebPack / Rollup и т.д ... для сопоставления импорта с глобальными объектами для запуска кода.

@billti Я не понимаю. Каков сценарий, в котором ваш единственный вариант - использовать глобальную версию модуля, но TypeScript не позволяет вам этого делать? Я видел только сценарии, в которых библиотека доступна и как глобальная, и как модуль.

@DanielRosenwasser Я думаю, он имеет в виду, что React на самом деле является глобальным во время выполнения, как в члене глобального объекта, из-за того, как он загружается.

@billti Замечательно, что у вас все работает.

По поводу второго пункта: я понимаю, о чем вы.

Я полагаю, что я чувствую, что в сценарии браузера, потому что вам нужно либо использовать загрузчик, такой как RequireJS, либо упаковщик, например Webpack, потому что ни один браузер не поддерживает модули, но это не имеет никакого значения. (Я слышал, что у Чакры он доступен за флагом). Таким образом, нет никакого способа запустить код без дополнительного инструмента. Это своего рода следствие вывода, содержащего define , require или System.register что сгенерированный код _JavaScript_ вряд ли будет переносимым. Тем не менее, я вижу важность различия «модуль против не модуля».

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

_shims.d.ts_

import __React from 'react';

declare global {
  const React: typeof __React;
}

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

Повторите свои shims.d.ts, если вы подниметесь на несколько постов, вы увидите, что я сделал это сейчас (великие умы думают одинаково) ;-)

Теперь я могу заставить его работать одним из нескольких способов, не в этом дело. Мы пытаемся упростить внедрение TypeScript, чтобы пользователи попадали в яму успеха, а не в яму отчаяния. Имея это в виду, я часто задаю себе два вопроса, пытаясь использовать TypeScript и сталкиваясь с проблемами: а) верен ли этот код и б) собираются ли клиенты попробовать это сделать.

Поскольку у меня была версия (не TypeScript), делающая то, что я хотел в Babel, примерно за то время, которое мне потребовалось, чтобы набрать ее, я думаю, будет справедливо сказать, что код действителен. Поскольку на странице установки документации React показано, как использовать теги сценария из CDN для включения React, я предполагаю, что ряд людей тоже попробуют это. (FWIW: я потратил больше времени, чем мне хотелось бы вспомнить, работая с различными модулями JS и загрузчиками, так что не то чтобы я их не знал, я просто хотел написать свой код таким образом).

Если TypeScript не собирается поддерживать определенные допустимые шаблоны написания кода, мы должны попытаться сделать это сразу очевидным и направить людей правильно (что является сложной задачей в сообщениях об ошибках или кратких документах). Но лично я не думаю, что TypeScript не должен поддерживать шаблоны, потому что мы не думаем, что они «лучшие практики» или «канонические». Если код действителен и некоторые разработчики JavaScript могут захотеть его написать, TypeScript должен попытаться поддержать его. Чем больше мы требуем, чтобы они изменили свой код и перенастроили конвейер сборки, чтобы заставить TypeScript работать (как это рекомендуется здесь для переноса моего тривиального приложения), тем меньше разработчиков перейдет на него.

Что касается решения ... здесь просто наплевать, но, возможно, параметр компилятора "lib", который уже эффективно определяет, какие API-интерфейсы доступны во всем проекте, также может принимать значения формата @types/name для глобального добавления библиотек (и, возможно, даже поддерживает относительные пути).

Мы пытаемся упростить внедрение TypeScript, чтобы пользователи попадали в яму успеха, а не в яму отчаяния.

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

  1. Создайте расширенную конструкцию export as namespace foo которая видна только в том случае, если она не импортирована модулем.
  2. Ничего не делайте и продолжайте подталкивать людей к использованию импорта - на мой взгляд, это более или менее нормально, поскольку мы в любом случае сделали сообщение об ошибке достаточно предписывающим.
  3. Разрешить людям использовать UMD отовсюду - я, честно говоря, не такой большой в этой идее.

@billti

Повторите свои shims.d.ts, если вы подниметесь на несколько постов, вы увидите, что я сделал это сейчас (великие умы думают одинаково) ;-)

Извините, я это пропустил, очень приятно;)

Я не думаю, что TypeScript не должен поддерживать шаблоны, потому что мы не думаем, что они «лучшие практики» или «канонические».

Я не думаю, что TypeScript здесь запрещает, я думаю, что он делает то, что утверждает, говоря мне, что у меня есть ошибка. Во многих библиотеках есть демонстрации и руководства, в которых они загружаются как глобальные объекты, а затем переходят к использованию синтаксиса модуля ES. Я не думаю, что, поступая так, они становятся величайшими гражданами, но это уже другой разговор.

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

Я думаю, что если люди используют TypeScript, по крайней мере, в файлах .ts , я предполагаю, что они хотят получить преимущества сильного статического анализа кода. Babel этого не делает, предполагая, что React существует, но не знает о нем. Это верно, даже несмотря на то, что модули ES были специально определены для статического анализа.

@DanielRosenwasser

Создайте расширенный экспорт как конструкцию foo пространства имен, которая видна только в том случае, если не импортирована модулем.

Похоже, это лучший способ решить эту проблему.

Вот еще один случай, когда это вызвало проблемы:

В проекте, над которым я сейчас работаю, мы смешиваем локальные включения (в основном по историческим причинам) с модулями npm. В конце концов, все объединяется с помощью Rollup или Browserify, так что это нормально.

Я использую файл .js из проекта emojione, который просто скопировал в кодовую базу. Позже я добавил объявления типов для него в DefinentyTyped: https://github.com/DefinitoTyped/DefinitiTyped/pull/13293 Я думал, что теперь могу просто загрузить типы, и все будет работать. Но похоже, что это не так, потому что TypeScript не позволяет мне получить доступ к глобальному.

Причина, по которой я не перехожу к модулю npm, заключается в том, что модуль npm также объединяет несколько мегабайт спрайтов и PNG. Мне просто нужен этот скрипт на 200 КиБ. С объявлениями типов.

С AngularJS обходной путь был declare var angular: ng.IAngularStatic . Но это не работает с пространствами имен, верно?

@dbrgn Вы столкнулись с другой проблемой. Если модуль на самом деле глобальный, то определение вашего типа неверно. Он не объявляет глобальный и не является объявлением стиля UMD (речь идет об объявлениях стиля UMD), он фактически объявляет только чистый модуль ES.

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

В AngularJS обходной путь был объявлен var angular: ng.IAngularStatic. Но это не работает с пространствами имен, верно?

Он работает с пространствами имен.

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

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

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

УГХ.

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

Мне не нужно подгонять 14 различных специальных стандартов модулей или пытаться скомпилировать js-модуль из исходных файлов в формате, который на самом деле будет использовать инструмент накопления / компоновки, не накапливая себя, а также будет генерировать формат модуля это будет хорошо работать с операторами импорта / экспорта Typescript и сторонними файлами d.ts, так что TSC действительно решит создать код вместо того, чтобы ныть о том, что вы собираетесь «ПРОСТО ИСПОЛЬЗУЙТЕ ЧЕРТОВЫЙ ИМПОРТ, ЭТО БУДЕТ ГЛОБАЛЬНЫМ В ВРЕМЯ РАБОТЫ ".

Хак shims.d.ts работает хорошо. Но тьфу.

Временное решение для тех, кто использует Webpack https://github.com/Microsoft/TypeScript/issues/11108#issuecomment -285356313

Добавьте externals в webpack.config.js с желаемыми глобальными объектами UMD.

    externals: {
        'angular': 'angular',
        'jquery': 'jquery'
        "react": "React",
        "react-dom": "ReactDOM"
    }

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

У меня есть проект, реализованный с помощью requirejs, где jQuery включен как глобальный, потому что есть некоторые плагины, которые расширяют jQuery, только если он найден как глобальный.

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

Кроме того, есть страницы, которые используют javascript без загрузчиков модулей. Итак, плагины должны работать как с глобальными объектами, так и с модулями.

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

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

Имеет ли смысл использовать для этого types в tsconfig.json ? Например, без types set вы получаете текущее неявное поведение, а с types set вы буквально говорите «эти вещи глобальные» и можете заставить пространство имен UMD появиться глобально. Такого рода поведение и так существует сегодня (без учета силы глобального). Это противоположно введению новой опции globals .

Думаю, это хорошая идея. В моем случае есть скрипты, которые используют одну библиотеку UMD как глобальную, а другие как модуль. Я мог бы решить эту проблему с помощью двух разных файлов tsconfig.json для каждого случая. Действительно прямолинейно.

@blakeembrey Хотя использование types имеет смысл, я не слишком увлечен идеей его перегрузки, поскольку у него уже есть проблемы. Например, конструкция <reference types="package" /> уже имеет ограничение, что она не поддерживает "paths" . "package" должно ссылаться на имя папки в @types

Мне сложно следить за этим разговором. Были ли какие-либо обновления или запланированные решения по этому поводу? Похоже, что это то, что может быть полезно в таких сценариях, как когда lodash является неотъемлемой частью приложения или когда больше сторонних библиотек преобразуются в более модульную структуру, а не просто полагаются на окно.

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

Привет, @mochawich, я получаю следующую ошибку при использовании определения React как внешнего и не использую синтаксис declare global :

TS2686: 'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.

@cantux TypeScript не читает конфигурацию Webpack. Если вы сделали React доступным глобально, вы можете declare это, но почему бы не использовать модули?

@aluanhaddad в основном потому, что меня смутила работа, выполняемая вызовом импорта. Я немного повозился, верны ли следующие утверждения?

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

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

Как @codymullins спросил выше, может ли кто-нибудь кратко

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

Мой сценарий таков:

  • в своих одностраничных приложениях я импортирую несколько библиотек (включая lodash) в

Упомянутый выше пример прокладки действительно работает, хотя vscode выделяет его как ошибку (хотя он по-прежнему выполняет завершение правильно!)

Пожалуйста, не давайте ошибок при доступе к глобальным UMD в модулях. Огромный проект, над которым я работаю, выполнен на AngularJS, и мы используем для приложения Typescript, но, конечно, нам нужен Typescript, чтобы знать о глобальных типах angular UMD и Angular из @types/angular . Вы могли подумать, что это так же просто, как добавить "angular" к types в tsconfig.json , но по какой-то причине это не так, и TSC кричит на меня. Как бы мне ни хотелось, чтобы все пакеты NPM были чистыми Typescript, большинство из них - это простой JS, и они будут такими еще очень долго. Я действительно не понимаю, почему TSC не может просто заткнуться, когда мы импортируем d.ts говоря, что присутствует глобальный UMD. Эта ситуация более чем обычна - каждый проект Typescript, над которым я когда-либо работал, использует по крайней мере одну библиотеку JS, которую я должен объединить и ссылаться на нее, используя определения типов.

Есть ли обновления по этому поводу?

Мой вариант использования: я работаю над большой существующей кодовой базой, которая интенсивно использует CDN. Общие утилиты импортируются через теги скриптов на многих страницах (например, clipboardjs, lodash). Я хотел бы сослаться на эти глобальные переменные, поскольку они доступны на странице. Без использования модулей достаточно легко выполнить компиляцию машинописного текста, используя /// <reference type="$name" /> в верхней части соответствующих исходных файлов. Однако это перестает работать при попытке создать модули.

Похоже, в ветке было предложено два подхода:

  1. Имейте токены импорта /// <reference type="$name" /> только в пространство имен текущего файла.

  2. Параметр компилятора / переменная конфигурации в tsconfig.json (например, "globals" , "types" )

Я считаю, что оба подхода хороши. Хотя я согласен с критикой варианта 1 со стороны @RyanCavanaugh :

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

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

Эта проблема все еще не решена? И если да, то каков текущий обходной путь?

Если вы устанавливаете пакет @types , те пакеты, которые не импортируются как модули, становятся доступными как глобальные.

Например, если я npm install -D @types/underscore в корне моего проекта, я могу писать модули, которые не импортируют ничего из подчеркивания, но глобальный _ будет доступен (см. Ниже).

types-ref

Это то, что тебе нужно?

@billti Может быть, я неправильно понял, но ваш пример мне не подходит.

Минимально необходимое для воспроизведения:

js / foo.ts:

// <reference types="js-cookie">

import { Bar } from "./bar";

const Foo = {
    set: function() {
        Cookies.set("foo", "bar");
    },
    get: function() {
        console.log(Cookies.get("foo"));
    }
};

window.onload = function() {
    console.log(Cookies);
}

js / bar.ts

const Bar = {
    x: 3
};

export { Bar };

package.json:

{
  "name": "foo",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "private": true,
  "devDependencies": {
    "@types/js-cookie": "^2.1.0",
    "typescript": "^2.7.1"
  },
  "dependencies": {
    "http-server": "^0.11.1"
  }
}

tsconfig.json

{
    "compilerOptions": {
        "module": "system"
    },
    "files": [
        "js/foo.ts"
    ]
}

Сообщения об ошибках:

js / foo.ts (7,3): ошибка TS2686: «Cookies» относятся к глобальному UMD, но текущий файл является модулем. Вместо этого рассмотрите возможность добавления импорта.
js / foo.ts (10,15): ошибка TS2686: «Cookies» относится к глобальному UMD, но текущий файл является модулем. Вместо этого рассмотрите возможность добавления импорта.
js / foo.ts (15,14): ошибка TS2686: «Cookies» относятся к глобальному UMD, но текущий файл является модулем. Вместо этого рассмотрите возможность добавления импорта.

Полученное вами поведение зависит от того, был ли импортированный модуль написан как «правильный» модуль UMD (это поведение с «куки») или как модуль «работает в обоих направлениях одновременно» (так пишется lodash). .

Непоследовательность того, что люди правильно пишут файл .d.ts, который описывает, как объект работает во время выполнения, и непрозрачность опыта для разработчиков - вот почему я довольно сильно склоняюсь к направлению «удалить глобальное ограничение UMD». Мы могли бы поместить его в --strict с отказом --noStrictUMD .

Еще я столкнулся с кастомным загрузчиком AMD Monaco. Они поддерживают некоторое подмножество поведения AMD (вставьте огромный глаз), но наступают на глобальное требование, поэтому очень сложно использовать с ним правильные модули UMD, поскольку эти модули, как правило, видят глобальный запрос, а затем не могут правильно загружаться в Загрузчик модулей Monaco. В конечном итоге вы помещаете библиотеки UMD JS над тегом скрипта для загрузчика Monaco, а затем TS жалуется, потому что вы получаете доступ к глобальным переменным из модуля (который должен быть у вас для импорта API Monaco).

@RyanCavanaugh

Еще я столкнулся с кастомным загрузчиком AMD Monaco. Они поддерживают некоторое подмножество поведения AMD (вставьте огромный глаз), но наступают на глобальное требование, поэтому очень сложно использовать с ним правильные модули UMD, поскольку эти модули, как правило, видят глобальный запрос, а затем не загружаются должным образом в Загрузчик модулей Monaco.

😁

Есть ли шанс, что они это исправят?

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

Как разработчики мы приняли инструментарий, который на порядки сложнее, чем 5-6 лет назад, и основным источником сложности были модули.

Если мы сдадимся и начнем загружать эти пакеты UMD как глобальные, для чего все это было?

И все же ... люди так и делают. Это ужасно!

Я имею в виду, что у этого ответа на переполнение стека 61 мкс, и он предлагал все неправильные вещи для 99% пакетов за последние полгода. (автор любезно обновил его, чтобы упомянуть модули как _option_ для зависимостей UMD из-за некоторых отзывов, предоставленных сегодня утром)

Это не может позволить всему этому вернуться к глобальным уровням!

И все же ... люди так и делают. Это ужасно!

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

Мы смешиваем и сопоставляем модули и глобальные объекты UMD, потому что слишком сложно загружать наши зависимости в виде модулей с разным уровнем совместимости с различными загрузчиками и некоторыми загрузчиками, не поддерживающими прямое связывание зависимостей, и вместо этого вы должны использовать наш специальный препроцессор, который принимает минута до бега.

Эта «особенность» просто означает, что мы не используем официальную поддержку модуля UMD, хотя на самом деле мы используем модули UMD. Мы просто экспортируем как глобал из файла .d.ts, а затем вручную создаем собственный модуль с таким именем, который реэкспортирует все.

Есть новости по этому поводу? Мне бы очень хотелось, чтобы вариант 2 работал:

Разрешите некоторый синтаксис или конфигурацию, чтобы сказать "этот глобальный UMD действительно доступен глобально"

Также не помогает то, что существует так много js-библиотек в старом стиле.
там, и о переписывании их всех речи быть не может. Просто прорабатываю твердую
config, чтобы получить Rollup для их правильной обработки, я трачу часы моего времени.

Люди смеются над "Enterprise Java", но обычная Java поставляется с работоспособным
модульная система на 1.0. Не было идеально, но и не было полным беспорядком.

Так как "Разрешить глобальные элементы в стиле UMD" обязательно должен быть вариант.

В пн, 2 апреля 2018 г., в 1:40 Kagami Sascha Rosylight <
[email protected]> написал:

Мне пришлось обходиться с:

/ * модуль: es2015 * /
// js-yaml поддерживает UMD, но не модуль ES2015! import * as _jsyaml из "js-yaml"; объявить var jsyaml: typeof _jsyaml; jsyaml.safeLoad ("");

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

>

Дэниел Джойс

Кроткие наследуют Землю, потому что храбрые будут среди звезд.

Я использую three.js в проекте Angular. Я импортирую это как

import * as THREE from "three";

import {Vector3} from "three"; также работает должным образом.

С установленными пакетами three и @types/three npm все работает нормально. Под капотом, я полагаю, используется three/build/three.module.js . В файле @types/three/index.d.ts используется обозначение export as namespace THREE , что мне не совсем удобно, но оно работает.

В этом конкретном случае проблема заключается в том, что в системе three.js есть еще один связанный файл с именем OrbitControls.js (который, в основном, позволяет вращать трехмерные изображения пальцем или мышью). Проблема в том, что, хотя эта функция полуофициально является частью дистрибутива three.js, это простой старый JS-файл, который находится в дереве examples и напрямую помещается в свойство THREE окна и напрямую использует другие API, которые он ожидает найти в window.THREE . Так что даже если мне "потребуется" файл с

require("three/examples/js/controls/OrbitControls.js");

он не может найти window.THREE чтобы надеть себя, или получить доступ к другим частям ТРИ системы, которую он использует. Я могу включить всю библиотеку напрямую, используя свойство Angular scripts в angular.json (примерно эквивалент старомодного тега <script> ), но затем, если я не ошибаюсь, я загрузит библиотеку дважды.

Чтобы избежать этого, я удалил оператор import * as THREE from "three"; , и, эй, он все еще может разрешать такие типы, как foo: THREE.Vector3 , но подавляется ссылками типа new THREE.Vector3() с печально известным

«ТРИ» относится к глобалу UMD, но текущий файл является модулем. Вместо этого рассмотрите возможность добавления импорта. [2686]

На данный момент я думаю, что мне просто нужно будет взять файл OrbitControls.js и ES6-ify и / или TS-ify, что, похоже, больше, чем один другой человек уже сделал в форма таких вещей, как `orbit-controls-es6 , так что, может быть, мне стоит просто упростить свою жизнь и использовать это, хотя я ненавижу отдавать свою жизнь в руки других людей таким образом.

На полунезависимом примечании одна странность заключается в том, что @types/three определяет типы для OrbitControls , даже если сам код не находится в самом модуле three . Однако я не могу понять, как связать все эти типы, определяющие класс с именем OrbitControls с чем-либо - я хотел бы объявить экспорт по умолчанию вышеупомянутого orbit-controls-es6 как этот тип, но как это сделать, ускользает от меня.

В конце концов я пришел к следующему решению, которого мне очень стыдно:

import * as THREE from "three";
Object.defineProperty(window, "THREE", {get() { return THREE; }});
require("three/examples/js/controls/OrbitControls.js");

Это работает, хотя я немного не понимаю, почему. В необходимом файле есть строка, например

THREE.OrbitControls = funtion() { };

который выглядит так, как будто в конечном итоге он будет назначен ТРИ "пространству имен" в результате оператора import * as THREE from "three"; , который не должен работать, не так ли?

@RyanCavanaugh попросил меня скопировать мой отзыв из # 26223 здесь:

Я поддерживаю довольно большую базу кода TypeScript (внутренний монорепозиторий Google), в котором есть несколько определенно типизированных библиотек, от которых зависят люди. Первоначально пользователи просто полагались на глобальные типы для библиотек, таких как angular , до того как .d.ts были превращены во внешние модули. Затем мы перенесли базу кода, чтобы использовать модули и явный импорт. На самом деле мы ожидали, что глобальные объекты UMD export as namespace d всегда будут требовать явного импорта для использования символов как для ссылок типа, так и для ссылок на значения, и даже не заметили, когда мы мигрировали (упс).

Разрешение использования неимпортированного кода для нас обычно проблематично:

  • это означает, что код полагается на определения глобальных «фоновых» типов, что затрудняет чтение кода (в частности, в браузерах репо или при просмотре кода без перехода к символу).

  • он скрывает зависимости кода

  • он обходит ограничения «должен иметь явную зависимость уровня сборки от всех импортов», которые мы реализуем в bazel, также известные как «strict deps».

    В большой базе кода ваш код должен иметь явные зависимости, иначе репо станет неуправляемым. Теперь, если у вас есть зависимость, связывающая A -> B -> C и глобальные типы, легко выполнить компиляцию кода A только потому, что B имеет зависимость от C . Если B позже удаляет свою зависимость, это нарушает A , что означает, что изменения имеют неожиданный волновой эффект в репозитории, нарушая изоляцию кода.

  • он заставляет код непоследовательно импортировать модуль с одним префиксом для значений и использовать его типы с другим префиксом (в частности, для AngularJS, ng vs angular)

Мы можем обойти это, удалив эти операторы export as namespace в нашей копии DefinitherTyped, предоставленной поставщиком, но, по крайней мере, для нас эта функция вроде как работает против удобства сопровождения кода и наших инженерных целей. Я думаю, что проблемы более выражены в ситуации с монорепорацией, такой как Google, но, как правило, также применимы к меньшим базам кода.

Пункты, которые вы разместили, абсолютно не важны для нашей ситуации. Мы вынуждены реализовывать наш собственный код с модулями AMD и предоставлять наши зависимости с модулями UMD из-за обстоятельств, которые в значительной степени находятся вне нашего контроля (но я бы резюмировал, как модули JS ужасно ошибочны как в концепции, так и в реализации). Эта функция позволит нам значительно упростить нашу жизнь.

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

Открытый вопрос: будет ли достаточно одного глобального флага для «Разрешить доступ ко всем модулям UMD», или людям действительно нужен контроль над ошибкой для каждого модуля?

Проголосуйте ❤️ за «всего один флаг»
Проголосуйте 🎉 за «необходимость контроля над модулями»

Я также рассматривал, не должно ли присутствие явного списка в параметре "types" в tsconfig.json также допускать использование UMD в модуле. Это означает, что тип присутствует намеренно. (Хотя, очевидно, это не исключает ошибки, которую вы забыли импортировать).

Или аналогично, использование конструкции /// <reference types="..." /> должно разрешить UMD использование этого пакета в модуле, в котором он используется (то есть упомянутый «элемент управления для каждого модуля»).

@RyanCavanaugh Будет ли флаг для адреса № 26233?

26233 считается полностью работоспособным по назначению; доступ к типовой стороне глобального UMD из модуля законно безвреден

Я не совсем уверен, «законно ли он безвреден». На примере @types/jquery . $ и jQuery отображаются на интерфейс JQueryStatic и экспортируются как константы. В результате все модули могут получить доступ к $ и jQuery без импорта. Надеюсь, я смогу это отключить.

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

На самом деле в случае с jQuery это влияет на emit. $() испускается в модуле без импорта.

Принятие PR для нового флага, который разрешает доступ к глобальным UMD из всех модулей.

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

На собрании по рассмотрению предложений мы назвали дюжину ужасных имен и возненавидели их всех.

Кем они были?

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

Может, umdUseGlobal или что-то в этом роде.

Я бы предложил importAllNamespaces в качестве имени глобального флага UMD, потому что глобальные переменные UMD обычно равны export as namespace .

@RyanCavanaugh Обсуждала ли команда проблему типа?

@FranklinWhale, да.

@saschanaz Уже спрашивал об этом, но мне также интересно ... @RyanCavanaugh Вы помните, какие ужасные имена обсуждались?

Я думаю, что цепочка пошла примерно так

  • allowUmdGlobalAccessFromModules - точнее всего, но очень долго
  • assumeGlobalUmd - тьфу
  • allowModuleUmdGlobals - "глобальные переменные" ??
  • umdAlwaysGlobal - 🤢
  • allowUmdGlobals - а я уже могу?
  • allowUmdGlobalAccess - пропускает модульную часть, но, наверное, никому нет дела?

Я бы выбрал последний, если бы

Спасибо!

Мне больше всего нравится allowUmdGlobalAccessFromModules потому что, хотя он длинный, его точность легче запомнить. Я бы подумал: «Что это за опция, позволяющая обращаться к глобальным объектам UMD из модулей? Ах да, конечно, это allowUmdGlobalAccessFromModules

Использование префикса «разрешить» соответствует соглашению об именах других параметров, и это хорошо.

Плюс ... есть и другие варианты примерно такого же размера :)

allowUmdGlobalAccessFromModules : 31 символ

allowSyntheticDefaultImports : 28 символов
strictPropertyInitialization : 28 символов
suppressExcessPropertyErrors : 28 символов
suppressImplicitAnyIndexErrors : 30 символов
forceConsistentCasingInFileNames : 32 символа

Каков текущий обходной путь? Я гуглил в течение последнего часа и не могу найти никаких рабочих решений.
Я бы предпочел не переводить на «любую» или понижать до рабочей версии Typescript, но не могу найти других вариантов.
Есть ли где-нибудь экспериментальная сборка, в которой есть флаг компилятора, который устраняет эту проблему?
(кстати, allowUmdGlobalAccessFromModules - отличное имя; не похоже, чтобы мы набирали его 50 раз в день :-))

Мы используем tsc 3.2.2 со статическим включением lodash в верхний HTML-файл; с require.js; d.ts, полученный из последней версии DefininiteTyped; пример кода, который не компилируется:

/// <reference path="..." />

class Example<T extends IThingWithTitle<T>> {

    public test = (arg : T[]) : void => {
        _.sortBy(arg, (el : T) => { return el.title; }); // TS2686: '_' refers to a UMD global, but the current file is a module. Consider adding an import instead.
    };

}

export = Example;

(пожалуйста, не говорите мне, что мне нужно перевернуть проект с ног на голову, я знаю, что в некоторых аспектах мы отстаем от графика)

Обновить: ((window) ._) / * FIXME https://github.com/Microsoft/TypeScript/issues/10178 * /. sortBy (...) работает, но, Господи, это некрасиво :-P

@Gilead , решение из этого комментария пока работает нормально: https://github.com/Microsoft/TypeScript/issues/10178#issuecomment -263030856

Есть ли в этом прогресс? У меня есть случай, когда упомянутый обходной путь, похоже, не работает (с использованием [email protected] ), потому что я столкнулся с этой проблемой.


Сначала я попробовал это:

import 'firebase';

declare global {
  const firebase;
}

Это неявно дает глобальному firebase тип any , а затем применяет к нему пространство имен (с тем же именем). Сначала казалось, что это работает, потому что он показывает правильные всплывающие подсказки / intellisense для всех ключей верхнего уровня firebase .

Однако на самом деле это не работает (я предполагаю, потому что затем он переключается на использование его как типа any , что может быть ошибкой?):


Поэтому я безуспешно пробовал описанный здесь обходной путь (хотя он работает и для других):

import _firebase from 'firebase'; // same with = require('firebase') 

declare global {
  const firebase: typeof _firebase;
}

=> 'firebase' прямо или косвенно упоминается в аннотации собственного типа.
(даже если пространство имен имеет псевдоним?)


Я тоже пробовал

import * as _firebase from 'firebase';

declare global {
  const firebase: typeof _firebase;
}

=> Круговое определение псевдонима импорта _firebase.
(может быть, из-за export = firebase; export as namespace firebase; в его определении ?)


И, наконец, если я просто сделаю import 'firebase' , я вернусь к

«firebase» относится к глобальному UMD, но текущий файл является модулем. [2686]


Если у кого-то есть решение для этого, он был бы очень признателен. В противном случае любые предложения по решению этой проблемы, которые были упомянуты до сих пор, кажутся мне действительно хорошими (флаг, ссылка на тройную косую черту, types в tsconfig, наличие объекта global или external в tsconfig).

Re комментарий @aluanhaddad

Это не может позволить всему этому вернуться к глобальным уровням!

Я не пытаюсь вернуться к глобальным переменным, я просто пытаюсь загрузить пару тяжелых зависимостей отдельно от моего пакета приложений, при этом все еще использую модули для всего остального, потому что это дает несколько преимуществ: зависимости можно правильно кэшировать потому что они не обновляются так часто, как мой комплект приложений; размер моего пакета не увеличивается (иногда из-за разделения кода сборщик включает одну и ту же зависимость несколько раз), что означает меньшую загрузку для пользователей моего приложения; восстановление моих пакетов во время разработки происходит намного быстрее.

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

@RyanCavanaugh Я изучил это и как бы понял, что мне нужно добавить параметр в compiler/types.ts и изменить глобальную проверку umd в compiler/checker.ts , и я думаю, мне нужно добавить его в compiler/commandLineParser.ts тоже ... но я думаю, что это займет у меня довольно много времени, потому что я совсем не знаком с источником (например, как добавить описание для флага CLI, не нарушая i18n) . А пока я буду ждать, пока кто-нибудь, кто уже знает источник, возьмется за дело.

@simonhaenisch Вы можете объявить его в файле объявления не модуля, и, чтобы избежать циклической ссылки, вы можете повторно экспортировать его в другое объявление модуля UMD. Исходный firebase объявлен как пространство имен, к счастью для нас, он дополнит наше объявление, не вызывая ошибки.

// umd.d.ts
import firebase = require("firebase");
export import firebase = firebase;
export as namespace UMD;

// global.d.ts
declare const firebase: typeof UMD.firebase;

К сожалению, мы объявили значение, а не пространство имен, поэтому вы не можете сделать что-то вроде let x: firebase.SomeInterface , единственный способ создать псевдоним пространства имен - объявить импорт, но вы не можете declare import firebase = UMD.firebase; , потому что пространство имен не увеличивает его. Конечно, мы можем использовать другое имя только для namspace, используемого в типе, но это вызовет путаницу, я бы предпочел отбросить остальной код, о котором я говорил выше, присвоить его глобальному значению во время выполнения, заставить псевдоним импорта действительно работать.

Как и в предыдущем комментарии, мы лениво загружаем hls.js (UMD) и ссылочные типы таким образом:

В hls.d.ts :

import * as Hls from 'hls.js';
declare global {
    const Hls: typeof Hls;
}

В файле .ts с использованием модуля UMD с отложенной загрузкой:

/// <reference path="hls.d.ts" />
// now use it
if(Hls.isSupported()){
 ...
} 

Протестировано в Typescript> = 3.0.1 и 3.4.1.

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

@MatthiasHild Можно ли это сделать без комментария /// <reference path="hls.d.ts" /> ?

ИЗМЕНИТЬ, да, это возможно, если объявление находится внутри включенного файла .d.ts , который НЕ имеет того же имени, что и другой файл .ts , на основе этого вопроса SO (это то, что меня и почему я спросил).

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

Смежные вопросы

dlaberge picture dlaberge  ·  3Комментарии

siddjain picture siddjain  ·  3Комментарии

Antony-Jones picture Antony-Jones  ·  3Комментарии

wmaurer picture wmaurer  ·  3Комментарии

CyrusNajmabadi picture CyrusNajmabadi  ·  3Комментарии