What is the best way to declare a global TypeScript variable in a definition file to make it accessible for import?

My issue revolves around an external JS library that contains a global parameter:

function Thing() {  ...  }
...
var thing = new Thing();

I have a TypeScript definition file named thing.d.ts with the following content:

declare var thing: ThingStatic;
export default thing;

export interface ThingStatic {
    functionOnThing(): ThingFoo;
}

export interface ThingFoo {
    ... and so on

To use this library in my own TS files, I import it like this:

import thing from 'thing';
import {ThingFoo} from 'thing';
...
const x:ThingFoo = thing.functionOnThing();

The problem arises when this code is transpiled to:

const thing_1 = require("thing");
...
thing_1.default.functionOnThing();

This leads to an error. After seeking help in another question, the suggestion was to try:

import * as thing from 'thing';

However, this does not resolve the issue - it introduces thing.default in TS, but once transpiled to JS, it remains undefined.

It appears that there might be an issue with thing.d.ts - there should be a way to define a typed global parameter for proper import.

How should thing.d.ts be written to accurately represent the JS without transpiling unnecessary properties like default which are not actually present?

Answer №1

If you find yourself in a situation where the only way to utilize a particular library is by accessing its global variables (rather than importing it as a node module, amd, or umd module), then the simplest approach is to create a declaration file without any explicit export statements at the top level. Simply declaring a variable will suffice. When compiling your TypeScript code, make sure to include this declaration file either by adding it to the files or include section in your tsconfig.json, or by direct command line inclusion. Additionally, remember to also include the library using a <script> tag at runtime.

For example: thing.d.ts

declare var thing: ThingStatic;

declare interface ThingStatic {
    functionOnThing(): ThingFoo;
}

declare interface ThingFoo {
}

test-thing.ts

const x: ThingFoo = thing.functionOnThing();

You can compile these files together like so:

./node_modules/.bin/tsc test-thing.ts thing.d.ts

The resulting test-thing.js file will look like this:

var x = thing.functionOnThing();

For more information on ambient declarations, refer to this question.

Please note that there are module loaders available that allow you to use global libraries as if they were modules, enabling you to use an import statement instead of a <script> tag. However, configuring these module loaders for such usage can be a more complex task.

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

Removing a checker piece in the game of checkers after successfully jumping over it

Recently completed a game of checkers and managed to figure out the logic for moving and jumping checker pieces. However, I'm now facing an issue with implementing the logic for removing or deleting a jumped-over checker piece. How can I automaticall ...

Is it possible to enable password authentication on Firebase even if the user is currently using passwordless sign-on?

In my frontend JS project, I have integrated Firebase for web and am utilizing the passwordless (email link) authentication method for users. I am now interested in implementing password sign-on for an existing user who is currently using passwordless si ...

Beginner in html, css, and javascript: "Tips for saving jsfiddle demos?"

Recently, I developed an interest in JavaScript and CSS and came across some impressive examples on jsfiddle. I was wondering if there is a way to "export" these examples to my computer. Simply copying and pasting doesn't seem to work. How can I modi ...

Looking to create circular text using HTML, CSS, or JavaScript?

https://i.sstatic.net/pnu0R.png Is there a way to generate curved text in HTML5, CSS3, or JavaScript similar to the image linked above? I've experimented with transform: rotate(45deg); but that just rotates the text without curving it. Additionally, ...

The screen suddenly turns black just moments after starting the video

Currently, I am utilizing the Youtube JavaScript API to embed videos on my webpage and control a playlist. However, I keep encountering an error where the video turns black right after loading the title, play icon, and loading icon. Initially, it seems lik ...

The node.js system automatically restarts an API call when a timeout occurs

Current Setup: I am using a combination of sails.js for the backend API and React for the frontend. The communication between the frontend and backend is handled by the fetch API. Scenario: Within some of my API endpoints, I need to run an external file ...

Rendering an element in React Router Dom based on specific conditions

Starting a new project with the latest version of react-router-dom and following their recommendation to use createBrowserRouter. The goal is to display a different header based on the path parameters. Currently, I have set up an optional path parameter: ...

Keep things in line with async functions in Node JS

Hello, I am just starting out with NodeJs and I have a question. I am trying to push elements into an array called files based on the order of the urls provided, but it seems like I'm getting a random order instead. Below is the code I've been wo ...

Creating a JSON object in JavaScript using an array

Can anyone assist me with the following code snippet for formatting the current month? var monthNames = ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set&apos ...

Using an array of strings as a key in React with TypeScript to access values from state

import React, { useState } from 'react'; interface PropsInterface { keys: string; // name,email,password } const Poster: React.FC<PropsInterface> = (props: PropsInterface) => { const [state, setState] = useState({ name: ' ...

Template string use in Styled Components causing issues with hover functionality

I have a styled component where I am trying to change the background color when its parent is hovered over. Currently, the hover effect is not working and I'm unsure why. const Wrapper = styled('div')` position: relative; margin-bott ...

Is it possible to calculate a variable within a dataset using existing data as a reference point?

Is there a way to dynamically compute some of the data variables in a Vue instance by referencing other variables and tracking their changes? new Vue({ el: '#root', data: { x: 1, y: x + 1 } }) <script src="https://cdnjs.cloudf ...

Is there a way for me to display information from a secondary child component by simply clicking a button on the main component instance?

Consider a scenario where there is a main instance, a child component named "movie-card," and another child component within "movie-card" called "link-btn." The objective is to create a selector that loops through the "link-btn" component using v-for. Addi ...

Discovering the orientation of an object in relation to the camera

I'm encountering a challenge in determining the angle of an object in relation to the camera. My goal is to write code for a spaceship with a camera that follows it. While I have successfully made the camera track the ship, there are instances where t ...

Adding a class to a Vue component using the $refs property

I am facing an issue where I need to add dynamic class names to various Vue components based on their reference names listed in a configuration file. Manually adding classes to each component is not feasible due to the large number of components. To addre ...

Disregard the JSON formatting and extract solely the values

After extracting data from an API, the format of the returned information looks like this: [{"id":21},{"id":22},{"id":24}] Next, I need to send this data to a database using a different API. However, the format for sending should be like this: [21,22,24] ...

How can I confirm that all elements have been properly reset to their original positions prior to making any further adjustments to them?

In need of some creative brainstorming, I'm working on a website design featuring ten overlapping cards. When the mouse hovers over a card, it expands while others move away. My goal is for each card to return to its original position once the cursor ...

Using AngularJS to automatically include predefined data in an $http request

I am looking for a way to include a default data attribute in an http request. I came up with the following code: var app = angular.module('dumbhttp', []); app.service('dumbhttp', function ($http, $location) { this.post = function ...

Is it better to use relative or absolute resource scripts in an AngularJS application?

My project involves building a single-page JavaScript app using AngularJS. In order to achieve this, the index.html file has a specific structure: <html> <head> <base href="/" /> ... </head> <body id="ng-app" ng-app="myAngularAp ...

Tips on organizing and designing buttons within a canvas

let canvas = document.getElementById("canvas"); let context = canvas.getContext("2d"); // for canvas size var window_width = window.innerWidth; var window_height = window.innerHeight; canvas.style.background="yellow" canvas.wid ...