What is the process of importing an IIFE-based JavaScript module into an Angular TypeScript application?

I have come across a third-party SDK that is structured as an oldschool IIFE based module. The code looks something like this:

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

  // Adding some methods to export

  return export;
})();

To use this SDK, one would typically reference it on the global scope like so:

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

While using it in this way is still possible, I am wondering if there is a better approach when working with Angular and TypeScript. Is there a way to configure angular/TypeScript/webpack environment to allow for proper import statements? Such as:

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

Answer №1

To ensure a proper import statement for the actual value of ThirdPartySDK, it is recommended to refactor the script into a module that exports this value. The code snippet below demonstrates how you can achieve this:

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

For larger libraries, refactoring may not be straightforward. In such cases, consider the following two approaches which require minimal refactoring:


1. Export the ThirdPartySDK variable

You can convert the IIFE file into a module by exporting the current IThirdPartySDK variable and then import it as follows:

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

    // Implement additional methods to export

    return _export;
})();

If you need information on the structure of ThirdPartySDK, add a type annotation to the const declaration. If SomeType is not defined, you will have to create it yourself:

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

To address any TypeScript errors related to assigning the IIFE expression to SomeType, use the as keyword:

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

2. Retain the <script> tag and declare the variable

An alternative approach is to keep the script tag, avoid importing anything, and declare the variable along with its expected type in TypeScript:

(You may need to provide the type definitions manually in this scenario)

interface SomeType {
    // Define SDK type structure here...
}

declare const ThirdPartySDK: SomeType;

Answer №2

To incorporate a third-party SDK into your TypeScript code, you can utilize a workaround involving the use of eval.

Consider the scenario where ThirdPartySDK.js has the following structure:

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

In this case, you would create a module called ThirdPartySDK-wrapper.ts with the following content:

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

global.eval(script);

//@ts-ignore
export default ThirdPartySDK;

The directive @ts-ignore is necessary to prevent TypeScript compiler errors related to the absence of a declaration for the ThirdPartySDK variable (which is declared within the eval-executed script).

You can then import and utilize ThirdPartySDK via the wrapper module:

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

Please note that this approach is specifically tailored for Node.js applications as it relies on fs.fileReadSync to fetch the script contents.

If you intend to employ this in a browser environment, alternatives must be explored to retrieve the script. One possible solution could involve leveraging tools like WebPack to package the ThirdPartySDK script as a string value that can be imported using require within the wrapper module.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using NextJS getServerSideProps to Transfer Data to Page Component

Having trouble with my JavaScript/NextJS code, and not being an expert in these technologies. I'm using the method export const getServerSideProps: GetServerSideProps = async () => {} to fetch data from an integrated API within NextJS. The code mig ...

Getting an error response with a status of 200 when making a jQuery ajax call

After sending a jQuery ajax request to my express-powered node.js server, everything seemed to be in order. However, to my surprise, the response invoked the error callback instead of the success callback, despite receiving a status code of "200". It was d ...

After performing the `ng build --prod` command in Angular 4, deep linking functionality may not

I have a requirement to display different screens in my Angular application based on the URL pasted by the user in the browser: http://localhost/screen1 (should show screen1) http://localhost/screen2 (should show screen2) To achieve this, I have set up ...

State calculation occurs too tardily

I'm working on creating a simple like button that changes color based on whether it's liked or not. I've tried to calculate this beforehand using React.useEffect, but it seems to be calculating afterwards instead... The hearts are initially ...

Using a Function as an Argument to Return an Unnamed Object

There seems to be a common trend in JavaScript code where a function is passed as a parameter, which in turn returns an anonymous object. myFunction(function() { return { foo: 'bar' }; }); What benefits or reasons are there for u ...

Troubleshooting Problem with Custom Class Buttons in Angular Material

Recently, I've been working on creating a custom class for angular material buttons. However, I encountered an issue where the button fades out or turns white when I click on it and then navigate away from the browser window (minimize it or activate a ...

The straightforward splitting of a string is yielding an object rather than an array

Attempting a simple string split in NodeJS is resulting in an unexpected outcome where it returns an object instead of an array. var mytext = "a,b,c,d,e,f,g,h,i,j,k"; var arr = mytext.split(","); console.log(typeof mytext); <======= output string conso ...

Test your unit by providing feedback to the personalized modal pop-up

Currently, I am working on a unit test within Angular where I need to evaluate the functionality of the save button. My goal is to have the 'save' option automatically selected when the user clicks on the button, and then proceed to execute the s ...

React-Query: executing a function after updating query data

After updating the cache in a form, triggered by a response from the server, I utilize setQueryData. However, following this cache update, my goal is to refocus on the form input field. Here are some details: Within my React application, I employ Recoil. ...

Achieve the highest character count possible within HTML elements

Is it possible for a standard HTML element with defined width and height to manage characters using JavaScript, as shown in the code snippet below? <div id="text-habdler-with-width-and-height" ></div> <script> $("element& ...

The "onChange" event does not seem to be triggering within an Angular HTML component

I am currently working on an HTML template for a component that displays all the doctors stored in the database along with a dropdown list of colors. The idea is that when a color is selected from the dropdown list, the onChange event should be triggered, ...

The internet explorer browser does not support the keypress event

i have the following code snippet: <input class="any" type="text" id="myId" name="myName" /> this specific input is using a jquery datepicker plugin.. (http://jqueryui.com/datepicker/) Here is my JavaScript for this element: $('#myId'). ...

What is the method to incorporate @angular/fire into an Nx Workspace for an Angular project?

Incorporating @angular/fire into my Nx workspace for my Angular application is my current goal. Despite my efforts to adhere to best practices, I have not found any guidance in the official documentation on how to incorporate this library into the wor ...

TS1316 Error: You can only have global module exports at the top level of the file

Encountering difficulties while trying to compile an older typescript project that I am revisiting. The build process is failing due to an issue with q. I suspect it may be related to the tsc version, but no matter which version I try, errors persist. Som ...

Finding the perfect pairing: How to align counters with objects?

public counter = 0; x0: any; x1: any; x2: any; x3: any; x4: any; next(){ this.counter += 1; this.storage.set("Count", this.counter); console.log(this.counter); this.logic(); } logic(){ //automatic counter here var xNum = JSON.parse(JSON.stri ...

Retrieve the key{index} property from the .map method in React for the element that was just clicked

I am facing an issue with my code const Component = () => { const [Clicked, setClicked] = useState(false); const handleClick = (prop, e) => { console.log(prop); } return ( <div> {arrayCard.map((item, i) => { ...

Are these two glob patterns distinct from each other in any way?

images/**/*.{png,svg} images/**/*.+(png|svg) After running tests on both expressions, it appears that they generally yield identical outcomes. However, it is crucial to confirm that they are indeed equivalent. ...

Once the user logs out, they have the ability to navigate back using the back button. What steps can be taken to address this

route.ts const appRoutes: Routes = [ { path: '', redirectTo: 'login', pathMatch: 'full' }, { path: 'login', component: LoginComponent }, { path: 'dashboard', canActiva ...

What is the best method for uploading and saving a file using AngularJS and ExpressJS together?

I am using a library for AngularJS called angular-file-upload. Despite successfully setting it up and getting image uploads to work, I am facing an issue with passing the file to the server side (express js). Jade: input.form-input(ng-model="userAvatarFi ...

Steps for launching a pop-up window in a response asynchronously

Hey there, I'm currently facing an issue with rendering a modal when my API response contains an error. Do you have any alternative suggestions on how to display a modal every time the API returns an error? const useEmbedContent = (resourceId) => { ...