2016-02-09 4 views
1

Я создаю модуль npm в TypeScript https://www.npmjs.com/package/html2commonmark. Модуль можно использовать в nodejs (с помощью require) и из браузера (путем загрузки node_modules/html2commonmark/dist/client/bundle.js в вашем браузере).Объявить глобальную переменную с использованием внешнего модуля в TypeScript

Я недавно добавил файлы * .d.ts, чтобы получить ввод информации при использовании "moduleResolution": "node". Это отлично работает, при установке моего модуля он готов к использованию в машинописном тексте. Таким образом: следующий код машинописного текста компилируется без ошибок:

// After installing using npm install html2commonmark 
// using "moduleResolution": "node" 
import * as html2commonmark from 'html2commonmark'; 
let converter = new html2commonmark.JSDomConverter(); 

Прекрасно!

Теперь я хочу запустить свой модуль в браузере. Как уже упоминалось ранее, мне нужно добавить тег сценария в node_modules/html2commonmark/dist/client/bundle.js на мою страницу index.html. После этого должна быть доступна глобальная переменная html2commonmark. Проблема в следующем: как я могу дать компилятору машинописного текста знать, что существует глобальная переменная? Следующий фрагмент кода TS не будет компилироваться:

let converter = new html2commonmark.BrowserConverter(); 
// error TS2304: Cannot find name 'html2commonmark'. 

Даже если я добавить файл global.d.ts, я, кажется, не быть в состоянии как импортировать мой внешний модуль и объявить свою глобальную переменную:

// Something like this does not work :(
import * as b from 'html2commonmark'; 
declare var html2commonmark: typeof b; 

Я понимаю, почему это так. Используя ключевое слово import, мой ts-файл преобразуется во внешний модуль и, следовательно, его нужно импортировать. Тем не менее, я чувствую, что мой сценарий является общим. А именно: модуль npm, содержащий как компонент npm, так и пакет для браузера, который предоставляет функциональность в качестве глобальной переменной.

Есть ли способ объявить глобальную переменную, используя определение внутри моего внешнего модуля? Я не чувствую, что переписываю api как пространство имен (ОпределенноТип-стиль), в то время как я просто написал весь свой исходный код в TS ...

ответ

2

Правильные способы написания внешнего модуля, который работает как в браузере, так и в Node.js является:

  1. используйте --module umd флаг, а затем использовать загрузчик AMD в браузере, чтобы загрузить модуль
  2. используйте --module commonjs флаг, а затем использовать Bundler как WebPack или browserify

Другими словами, когда вы текстовый модульный код, слепо добавляя <script> теги в HTML-файл уже не является правильным способом загрузить этот код в браузер. Так же, как вы не должны касаться глобальной области в Node.js, вы также не должны касаться глобальной области действия в браузере. Вы можете взломать его с помощью if (typeof window !== 'undefined') (<any>window).global = yourObject;, но серьезно, не делайте этого, это неправильно, и он сломается.

Что касается предоставления интерфейсов внутри внешних модулей в глобальном масштабе, нет никакого способа сделать это, так как вам придется import внешний модуль, чтобы получить ссылку на его интерфейсов, в этот момент у Вас есть создал другой внешний модуль. Начиная с TypeScript 1.8, вы можете увеличить глобальные типы из внутренних модулей, используя declare global.

+0

Спасибо за ваш ответ! Для создания bundle.js я использую webpack. Конечно, я мог бы также заставить (машинописных) потребителей писать для браузера использовать webpack/browsify. Мне просто интересно, есть ли лучший способ. Я чувствую, что это должно быть возможно. с использованием окна '() .global = yourObject' не требуется, поскольку объект уже доступен в глобальной области действия (по крайней мере: при включении объекта bundje.js на вашей странице). Я просто ищу способ сделать его видимым для машинописного текста. – nicojs

+0

В этом случае ответ гораздо проще «нет». Вы можете выставить глобальные интерфейсы для именованных модулей в рукописных файлах d.ts с помощью 'declare module 'foo" {export = SomeGlobal; } ', но пути в другом направлении нет. –

+0

Это очень плохо. Если вы обновите свой ответ с помощью короткой версии, я отметю его как правильный ответ. – nicojs

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