What is the best way to make a class available in the global namespace within a TypeScript module?

The Issue at Hand

Given an existing application with a mixture of modules and global scripts, the goal is to convert one class in a global script (gamma.ts) into a module. This entails adding `export default` before `class gamma {}` in gamma.ts. Additionally, the objective is to import the gamma class into the global namespace (window object) for accessibility by both global and module scripts.

Approaches Taken So Far

Several attempts have been made involving global.d.ts file.

For instance:

import gammaAlias from "../scripts/gamma";
export as namespace NS_Global;

declare global {
    var qqq: {n:string};
    namespace ZZZ {
       export var gamma: gammaAlias;
    }
    var gamma: gammaAlias;
}

Despite these efforts, TypeScript has thrown errors such as "gamma does not exist" or "Cannot use 'new' with an expression whose type lacks a call or construct signature."

Exploring on GitHub

To delve deeper into this issue, check out my GitHub repository: https://github.com/penguin020/expose-typescript-modules-globally

The ConvertToModulesPOC_original represents the functional "before" scenario.

In contrast, ConvertToModulesPOC signifies an unsuccessful effort to convert gamma .ts to a module and expose it globally.

Final Notes

The core question remains - how can a module be exposed to the global namespace? Any insights utilizing the provided examples in the GitHub repository would be highly appreciated!

Answer №1

I stumbled upon a solution in the article "TypeScript: exposing module types in the global context and why to avoid it";

After reading, I made updates to the repository on GitHub.

The key changes that caught my attention were:


in tsconfig:

"module": "system",

within yMod.ts

import gammaAlias from "../scripts/gamma.js";

declare global {
    export type gamma = gammaAlias;
    export const gamma: typeof gammaAlias;
}

(window as any).gamma = gammaAlias;

Note: The global ambient declaration could also be placed in another file, even a *.d.ts file.


The provided link explains the rationale behind having three references for each symbol to be exposed globally. The page elaborates well on this topic, so here's a brief summary:

  1. Expose the class type to the TypeScript compiler (no code generated)
  2. Expose the class object to the TypeScript compiler (to allow instantiation with new; no code generated)
  3. Extend the window object to expose the class in the global namespace (generates code).

Answer №2

If I understand correctly, your goal is to make 'gamma' accessible in the global scope for easy access to 'gamma.log()' from either 'window' or the console.

To achieve this, insert the following 2 lines at the end of the gamma.ts file:

let g = new gamma();
(window as any).gamma = g

Explanation:

1) The first line creates a new instance of the Gamma class and stores it in the variable g.

2) The second line makes g available globally under 'window.g' or simply 'g'.

See the screenshot for reference: Screenshot

For further details, refer to Pull request #1: https://github.com/penguin020/expose-typescript-modules-globally/pull/1/files


It may be beneficial to move these code lines to your main initialization file 'app.js' for better organization.

Contents of gamma.ts:

export default class gamma {

Contents of app.ts:

import gamma from "./gamma";
let g = new gamma();
(window as any).gamma = g

Find more information in Pull request #2: https://github.com/penguin020/expose-typescript-modules-globally/pull/2

Answer №3

This solution fits perfectly with my needs. The only thing I find inconvenient is having to change the interface name.

declare global {
  interface IMyClass extends MyClass { }
}

class MyClass {

}

or

declare global {
  type IMyClass = MyClass;
}

class MyClass {

}

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

Some code paths fail to return a value in Google Cloud Function callable functions

When utilizing async functions in my cloud function and including a 'return' statement in each potential output, I am still encountering the error message Not all code paths return a value I attempted removing my database calls and only leaving ...

What is the best method for translating object key names into clearer and easier to understand labels?

My backend server is sending back data in this format: { firstName: "Joe", lastName: "Smith", phoneNum: "212-222-2222" } I'm looking to display this information in the frontend (using Angular 2+) with *ngFor, but I want to customize the key ...

Error in Angular: Http Provider Not Found

NPM Version: 8.1.4 Encountered Issue: Error: Uncaught (in promise): Error: Error in ./SignupComponent class SignupComponent_Host - inline template:0:0 caused by: No provider for Http! Error: No provider for Http! The error message usually indicates the a ...

Updating data in Angular reactive forms using asynchronous dropdowns

I am currently developing an Angular application and have encountered an issue that I am unable to resolve by solely reading the documentation. One of the components in my application is responsible for displaying a form: https://i.stack.imgur.com/p5KEU. ...

The 'DOCUMENT' module (imported as 'i23') could not be located within '@angular/platform-browser'

During my upgrade from Angular version 7 to 8, I encountered an error when building the project even though I am not using DOCUMENT. It seems like something is causing this issue that I am overlooking. I have thoroughly checked all the files and confirmed ...

The element does not recognize the property 'width' since it is not defined in the type of 'GlobalEventHandlers'

I'm trying to determine the size of an image using JavaScript, but I encountered a TypeScript error: const img = new Image(); img.onload = function() { alert(this.width + 'x' + this.height); } img.src = 'http://www.google.com/intl/en_ ...

Utilizing the FormsModule and ReactiveFormsModule within a Component module

I am facing an issue with integrating a reactive form into a generated component called boom-covers. I am utilizing the [formGroup] property as shown below: <form name="boomCovers" method="post" id="bomCovers" (ngSubmit)=&q ...

Using React.Fragment in VS Code with TypeScript error 2605 while having checkJs enabled

While utilizing the JS type checking feature in VScode, I encountered an issue with React.Fragment that is being linted with an error: JSX element type 'ReactElement<any>' is not a constructor function for JSX elements. Type 'ReactEle ...

The object does not contain a 'navigation' property within the 'Readonly<{}> & Readonly<{ children?: ReactNode; }>' type

As a beginner in react native, I am facing some challenges with the components I have created. Let me share them: List of Playlists: export default class Playlists extends Component { playlists = [ ... ]; render() { const {navigation} = th ...

Tips on refreshing a view in react as data updates

Currently, I am delving into learning a variety of subjects such as Typescript, Express, and my newfound interests in REACT and RXJS. To aid in my studies, I created a Quick-List on Github, but encountered a question... "How can the view in React be upda ...

What are the steps to ensure a successful deeplink integration on iOS with Ionic?

Recently, I was working on a hybrid mobile app for Android/iOS using Nuxt 3, TypeScript, and Ionic. The main purpose of the app is to serve as an online store. One important feature involves redirecting users to the epay Halyk website during the payment pr ...

Do changes in Input fields reflect in the parent component?

I was under the impression that I could share data with child components using @Input() directive and communicate data back to the parent component with @Output() along with the appropriate emit. However, I recently discovered that modifications made to th ...

The 'in' operator is unable to find 'colour' within true (function return type)

Here's the TypeScript code I'm working with: let a: unknown = true; if(hasColour(a)) { console.log(a.colour); // Using a.colour after confirming a has the colour property } I've created a function to check if the color property exist ...

What is the best way to trigger a useReducer dispatch function from a different file that is not a React component, without relying on Redux?

In my project, I have a function component that shows a game board named "EnemyBoardComponent.tsx" const enemyBoardReducer = (state:number[][], action:Action)=>{ switch(action.type){ case "update": { return EnemyBoard.getGrid(); ...

Unable to utilize MUI Dialog within a ReactDOMServer.renderToStaticMarkup() call

I recently started using the DIALOG component for the first time, expecting it to seamlessly integrate into my setup. However, much to my disappointment, it did not work as expected. After spending a considerable amount of time troubleshooting the issue, I ...

"Encountering difficulties while setting up an Angular project

I am currently working on setting up an Angular project from scratch. Here are the steps I have taken so far: First, I installed Node.js Then, I proceeded to install Angular CLI using the command: npm install -g @angular/cli@latest The versions of the ...

Inheritance in Angular with TypeScript Using Generic Types

Looking for some assistance from the angular2 / typescript experts out there to guide me in the right direction before I lose my mind :-) Here's what I'm trying to achieve: I want to create a parent class that implements its own defined parent ...

Troubles with Jest tests are encountered when using ts-jest in an ES2020/ESNEXT TypeScript project

Currently, I am working on a VueJS project that utilizes ViteJS for transpilation, which is functioning properly. However, when Jest testing is involved alongside ts-jest, the following Jest configuration is used: jest.config.ts import { resolve } from &q ...

What is the reason behind In-memory-web-api not generating an ID?

While I have successfully implemented the GET, PUT, and DELETE methods using InMemoryDbService to simulate an API, I am facing issues with the CREATE method. It seems like the ID is not being generated in the route to display my add form. The error message ...

Fix React/Typescript issue: Exported variable conflicts with name from external module

I am encountering a perplexing issue when using React with Redux and Typescript. The error message I am receiving is unfamiliar to me, and I am unsure how to resolve it. The error states: Exported variable 'rootReducer' has or is using name ...