Как импортировать модуль JavaScript на основе IIFE в приложение Angular TypeScript? - PullRequest
0 голосов
/ 17 января 2019

Итак, у меня есть сторонний SDK, написанный как модуль oldschool IIFE. Другими словами это выглядит примерно так:

var ThirdPartySDK = (function() {
  var export = {};

  // Add some methods to export

  return export;
})();

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

<html>
  <body>
    <script src="lib/ThirdPartySDK.js">
    <script>
      ThirdPartySDK.foo();
    <\script>
  <\body>
<\html>

Конечно, я все еще мог бы использовать это, но действительно ли это лучшая практика с Angular и TypeScript? Есть ли способ настроить вещи с помощью angular / TypeScript / webpack, чтобы я мог использовать правильный оператор импорта? Примерно так:

import { ThirdPartySDK } from '../lib/ThirdPartySDK.js';
ThirdPartySDK.foo();

Ответы [ 2 ]

0 голосов
/ 17 января 2019

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

Допустим, что ThirdPartySDK.js выглядит так:

var ThirdPartySDK = (function () {
    var exports = {
        foo: function () { console.log("Hello, world!"); }
    };
    return exports;
})();

Затем вы должны создать модуль ThirdPartySDK-wrapper.ts, который будет выглядеть примерно так:

import * as fs from 'fs';
const script = fs.readFileSync('../lib/ThirdPartySDK.js').toString();

global.eval(script);

//@ts-ignore
export default ThirdPartySDK;

Директива @ts-ignore требуется, чтобы компилятор TypeScript не жаловался на то, что не нашел объявление для переменной ThirdPartySDK (оно объявлено в скрипте, выполняемом через eval).

Затем вы можете импортировать ThirdPartySDK через модуль оболочки:

import ThirdPartySDK from './wrapper';
ThirdPartySDK.foo();  // Console output: "Hello, world!" 

Обратите внимание, что эта оболочка работает только для приложений, работающих в Node.js, поскольку она использует fs.fileReadSync для получения содержимого скрипта.

Если вы собираетесь использовать его в браузере, вам понадобится другой способ получить скрипт. Возможно, вы могли бы использовать такие инфраструктуры, как WebPack, для связывания сценария ThirdPartySDK в виде строкового значения, которое вы можете require в модуле оболочки.

0 голосов
/ 17 января 2019

Лучший способ получить правильную инструкцию импорта для фактического значения из ThirdPartySDK - это реорганизовать скрипт в модуль, который экспортирует это значение. Следующий фрагмент позволяет использовать оператор импорта, как показано:

export const ThirdPartySDK = {
    foo() { console.log('Doing foo'); }
};

Для больших библиотек рефакторинг не всегда так прост, поэтому я вижу 2 подхода, которые не требуют слишком много рефакторинга:


1. Экспортируйте ThirdPartySDK переменную

Вы можете просто сделать модуль из файла IIFE, экспортировав текущую переменную IThirdPartySDK (возвращаемую IIFE), а затем импортировать ее, как показано:

export const ThirdPartySDK = (function() {
    var _export = {};

    // Add some methods to export

    return _export;
})();

Обратите внимание, что если вы хотите получить некоторую полезную информацию о форме ThirdPartySDK, вам необходимо добавить аннотацию типа в объявление const, и если SomeType (см. Ниже) еще не существует, вы '' Я должен написать это сам:

export const ThirdPartySDK: SomeType = (function() {
// ...

В этот момент Typescript начнет жаловаться на то, что выражение IIFE не может быть присвоено SomeType; быстрое «решение», позволяющее машинописи делать вид, что выражение выражается значением типа SomeType с использованием ключевого слова as:

export const ThirdPartySDK: SomeType = (function() {
    // ...
})() as SomeType;

2. Сохраните тег <script> и объявите переменную

Другой вариант - сохранить тег script, ничего не импортировать и объявить переменную и ее ожидаемый тип в машинописи:

(но в этом случае вам, возможно, придется самим давать определения типов)

interface SomeType {
    // SDK type shape goes here...
}

declare const ThirdPartySDK: SomeType;
...