TypeScript's cross-environment global variable with a predefined default value

Issue

Imagine a library with an unlimited number of functions, each residing in its own file:

  • doSomethingAlpha.ts
  • doSomethingBravo.ts
  • doSomethingCharlie.ts
  • ...

Some functions reference the global variable __LANGUAGE_CODE__:

export default function doSomethingAlpha(): void {
  if (__LANGUAGE_CODE__ === "en") {
    console.log("English");
  } else if (__LANGUAGE_CODE__ === "ja") {
    console.log("日本語");
  }
  // ...
}

The __LANGUAGE_CODE__:

  • Should not rely on the environment (functions may be used in either a browser or Node.js, but must first be compiled to JavaScript and bundled into the user's project). This rules out using window.
  • Comes with a default value that can be changed by anyone using the library:
export { doSomethingAlpha } from "library";

doSomethingAlpha(); // "English"

__LANGUAGE_CODE__ = "ja";

doSomethingAlpha(); // "日本語"

Additionally:

  • The library is distributed without being pre-compiled to JavaScript (so no Webpack DEFINE plugin usage). Users of the library can bundle it to their projects using Webpack (or just TypeScript compiler), but the library itself is unaware of Webpack.
  • The library lacks a centralized entry point: users only take the specific function they need.

Innovative Solution Considerations

We could inform TypeScript about __LANGUAGE_CODE__ within the library by creating a **.d.ts file and declaring:

declare const __LANGUAGE_CODE__: string;

An unresolved issue remains regarding how to set the default value.

export { doSomethingAlpha } from "library";

doSomethingAlpha(); // no output because "__LANGUAGE_CODE__" is undefined

Answer №1

Step 1: Setting up the global variable

declare global {
  var __LANG_CODE__: string;
}

Take note of using var. This allows access to __LANG_CODE__ as globalThis.__LANG_CODE__, window.__LANG_CODE__, and simply as __LANG_CODE__. Using let or const would not work in the same way.

Step 2: Assigning a default value

This should be done early in your application.

globalThis.__LANGUAGE_CODE__ = 'en';

If your library does not have a single entry point, you can advise users to either

  • assign a value themselves, or
  • import a module created by you before using your library. This imported module will modify their environments.

For instance, place your definition in

"library/environment.ts"
.

environment.ts

globalThis.__LANGUAGE_CODE__ = 'en';

User code:

import "library/environment";
export { doSomethingAlpha } from "library";

doSomethingAlpha();

Note: every library has an entry point, usually defined by the main field in your package.json. If your main is just a barrel file (it only re-exports contents of other modules), you can also define the default __LANGUAGE_CODE__ there.

Step 3: Accessing the variable

__LANGUAGE_CODE__ can now be accessed and modified using these methods.

globalThis.__LANGUAGE_CODE__;
window.__LANGUAGE_CODE__;
__LANGUAGE_CODE__;

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

The dynamically loaded JavaScript file was unable to access the constructor, resulting in the error message "X is not a constructor."

Attempting to eliminate the use of import statements and instead dynamically load Javascript files using a specific class. This particular class is used for this purpose: export function JSImport<T>( importPromise: Promise<T>, ): Promise&l ...

Developing sophisticated search entities through coding and inputting diverse search attributes

Exploring New Territory In the process of developing a Next app, I'm delving into the realm of advanced search forms. To streamline this task, I've stumbled upon a handy library called search-query-parser. With the magic of search-query-parser, ...

having difficulty running unit tests in Angular 8 with .NET Core

Every time I try to execute ng test command I am faced with this particular error message: [error] Error: error TS6046: The argument specified for the '--target' option should be one of the following: 'es3', 'es5', &apos ...

Angular 6: TypeError - The function you are trying to use is not recognized as a valid function, even though it should be

I'm currently facing a puzzling issue where I'm encountering the ERROR TypeError: "_this.device.addKeysToObj is not a function". Despite having implemented the function, I can't figure out why it's not functioning properly or callable. ...

The current value of React.createRef() is perpetually empty

Ever since I started working on this code, I've been encountering a problem that seems to have no solution. Here's what's going on: import React, { Component } from 'react'; export class InfoPaneArrow extends Component<InfoPane ...

`Placement of ion-popover in relation to ion-modal`

I'm facing an issue with displaying an information popover within a modal. The popover is not appearing in the correct location, even when I pass the event to the popoverController. Is there a way to make the popover appear just under the information ...

Filtering an array of objects based on duplicate properties using Typescript

I am looking to filter an array of objects in order to extract only the objects with duplicate property values. This is my Array of Objects: data = [ { id: 1, name: 'apple' }, { id: 2, name: 'banana' }, { id: 3, name: 'cherr ...

`In TypeScript Angular, encountering challenges with accessing object properties`

My TypeScript object looks like this const playlist: { tracks: Array<Track> } = { tracks: new Array<Track>() }; This is the Track interface I am working with interface Track { title?: string; album?: string; artists?: string; duration? ...

Testing a recursive function that invokes a function which returns a promise

In the code snippet I am testing, there is a simple queue that gets periodically emptied. Each number in the queue triggers an HTTP POST request to send it to a fictional API address. If the POST is successful, the number is removed from the queue and the ...

Issue with Aligning Datepicker Interface

Displayed above its corresponding input element or sometimes vertically anywhere on the page. I am looking to have it appear below the input element instead. https://i.sstatic.net/nEDwc.png https://i.sstatic.net/pVbhG.png Currently, it is overlapping it ...

Trouble accessing the Ionic SQLite database: Unable to open

I encountered some errors while attempting to connect my ionic app to a database. I am currently running the app on an android device using Google Chrome DevTools to troubleshoot the issue. Check out the createDatabase() function and the specific error th ...

Is there a way to utilize Typescript enum types for conditional type checking?

I'm working with restful services that accept enum values as either numbers or strings, but always return the values as numbers. Is there a way to handle this in TypeScript? Here's my attempt at it, although it's not syntactically correct: ...

Comparison: executing an immediately invoked function expression (IIFE) and a separate

During my recent refactoring of some legacy code, I stumbled upon the following example: // within another function const isTriggerValid = await (async () => { try { const triggers = await db.any(getTriggerBeforeBook, { param ...

What steps are required to customize a pre-existing DevExtreme JQuery DataGrid that was initially built in a cshtml file using Typescript?

I'm currently developing a web application using DevExtreme JQuery. Within the frontend, I have set up a DataGrid in a cshtml file. With DevExtreme functionality, it's possible to include an Add Button to the DataGrid that triggers a popup for in ...

In the Angular Google Maps API, is it possible to update the attributes of <agm-marker> directly within the TypeScript code?

Currently, I am fetching markers from the database and displaying them on a map using Angular Google Maps (AGM) by utilizing the <agm-marker> tag. In my code snippet below, you can see how I fetch and store the markers in an array named markers in t ...

Angular 4 allows for checkboxes to be automatically marked as checked when the value is true

I have a question regarding how to automatically check a checkbox under certain conditions. Specifically, I have a situation where the accept() function triggers the onApprovedDateChecked() function with a true parameter. When this happens, I need the chec ...

Avoid using <input oninput="this.value = this.value.toUpperCase()" /> as it should not convert the text displayed on the "UI", rather it should send the uppercase value

<input oninput="this.value = this.value.toUpperCase()" type="text" id="roleName" name="roleName" class="form-control width200px" [(ngModel)]="role.roleName"> Even though the UI is changing ...

Encountering a problem with Typescript and eslint while utilizing styled-components and Material UI: "Warning: React does not identify the `showText` prop on a DOM element."

While using a styled component to return a material ui Fab component, an error appears in the console: React does not recognize the `showText` prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as low ...

Encountering Duplicate Identifier Error while working on Angular 2 Typescript in Visual Studio Code

Currently attempting to configure a component in Angular 2 with Typescript using Visual Studio Code on Mac. Encounter the following errors when trying the code below: duplicate identifier 'Component'. and Duplicate identifier' DashboardCompo ...

What are the reasons for an object potentially being undefined following a *ngIf evaluation in Angular 14?

There is a scenario where we have an object defined by an interface, with the option for both category and its nested name: export interface Product { category?: { name?: string, } } The objective now is to display an element only if both the cate ...