Complete Guide to Creating Global Variables in TypeScript

Nov 20, 2025 · Programming · 28 views · 7.8

Keywords: TypeScript | Global Variables | eval Function | Declaration Merging | Module Scope

Abstract: This article provides an in-depth exploration of various methods for creating global variables in TypeScript, with a focus on the eval function hack solution and its applicable scenarios. It explains the differences between global scope and module scope, the special role of the var keyword in global declarations, and how to extend global interfaces through declaration merging. Complete code examples and best practice recommendations are provided to help developers choose appropriate global variable implementation solutions based on specific requirements.

Overview of Global Variables in TypeScript

While creating global variables is relatively straightforward in JavaScript, TypeScript's strict type checking and module system require specific approaches. This article provides a detailed analysis of various technical solutions for creating global variables in TypeScript based on practical development needs.

Core Problem Analysis

From the Q&A data, developers want to achieve global variable functionality in TypeScript similar to JavaScript, where global variables can be accessed directly without the window. prefix. This involves core characteristics of TypeScript's type system and module mechanism.

Hack Solution Using eval Function

Based on the best answer (Answer 4), we can use the eval function combined with type declarations to implement global variables:

// Type declaration
declare var something: string;

// Setting global variable using eval
eval("something = 'testing';");

// Direct usage in other files
if (something === 'testing') {
    console.log("Global variable access successful");
}

The principle of this method is to use the eval function to bypass TypeScript's type checking and dynamically set global variables at runtime. Simultaneously, the declare var declaration provides type information for the TypeScript compiler, ensuring the code compiles normally.

Differences Between Global Scope and Module Scope

TypeScript files operate in two different scope modes:

Global Scope

When a file contains no import or export statements, it operates in global scope. In this mode, variables declared using the var keyword become global variables:

// global.ts - No import/export statements
var globalVar: string = "This is a global variable";

// other.ts - Direct access
console.log(globalVar); // Output: This is a global variable

It's important to note that only the var keyword is effective in global scope; variables declared with let or const do not become global variables.

Module Scope

When a file contains import or export statements, it operates in module scope. In this mode, global interfaces need to be extended through declaration merging:

// types/global.d.ts
declare global {
    var moduleGlobalVar: string;
}

export {}; // Ensure the file is treated as a module

// main.ts
import './types/global';
globalThis.moduleGlobalVar = "Global variable in module scope";

// other.ts
console.log(globalThis.moduleGlobalVar); // Output: Global variable in module scope

Global Variables Based on Window Object

In browser environments, global variables can be created by extending the Window interface:

// types/window.d.ts
interface Window {
    browserGlobal: string;
}

// main.ts
window.browserGlobal = "Browser global variable";

// other.ts
if (window.browserGlobal === "Browser global variable") {
    // Business logic
}

Global Variables in Node.js Environment

In Node.js environments, implementation can be achieved by extending the NodeJS.Global interface:

// types/node.d.ts
declare global {
    namespace NodeJS {
        interface Global {
            nodeGlobal: string;
        }
    }
}

export {};

// app.ts
global.nodeGlobal = "Node.js global variable";

// other.ts
console.log(global.nodeGlobal); // Output: Node.js global variable

Practical Application Scenario: Logging System

Based on the logging system requirement mentioned in the Q&A, we can implement a global logging utility:

// types/logger.d.ts
declare global {
    namespace NodeJS {
        interface Global {
            log: {
                Debug: (message: string) => void;
                Info: (message: string) => void;
                Error: (message: string) => void;
            };
        }
    }
}

export {};

// logger-setup.ts
import './types/logger';

global.log = {
    Debug: (message: string) => {
        console.log(`[DEBUG] ${new Date().toISOString()}: ${message}`);
    },
    Info: (message: string) => {
        console.log(`[INFO] ${new Date().toISOString()}: ${message}`);
    },
    Error: (message: string) => {
        console.error(`[ERROR] ${new Date().toISOString()}: ${message}`);
    }
};

// any-file.ts
// No import needed, use global log directly
global.log.Debug("This is a debug message");
log.Info("This is an info message"); // If configured correctly, global prefix can be omitted

Best Practices and Considerations

Type Safety Considerations

When using global variables, ensure complete type definitions are provided to avoid runtime type errors:

// Complete type definition
declare global {
    var appConfig: {
        apiUrl: string;
        timeout: number;
        debugMode: boolean;
    };
}

// Provide complete object during initialization
globalThis.appConfig = {
    apiUrl: "https://api.example.com",
    timeout: 5000,
    debugMode: true
};

Avoiding Global Pollution

Minimize the use of global variables to avoid naming conflicts:

// Use namespace isolation
declare global {
    namespace MyApp {
        var config: any;
        var utils: any;
    }
}

globalThis.MyApp = {
    config: {},
    utils: {}
};

Configuring TypeScript Compiler

Ensure tsconfig.json is properly configured to include type declaration files:

{
    "compilerOptions": {
        "typeRoots": ["./types", "./node_modules/@types"]
    },
    "include": ["src/**/*", "types/**/*"]
}

Conclusion

There are multiple methods for creating global variables in TypeScript, each with its applicable scenarios:

In practical development, it's recommended to prioritize declaration merging approaches as they provide the best type safety and code maintainability. Consider alternative solutions only in specific scenarios.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.