Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I have a node.js app that attaches some config information to the
global
object:
global.myConfig = {
a: 1,
The TypeScript compiler doesn't like this because the Global
type has no object named myConfig
:
TS2339: Property 'myConfig' does not exist on type 'Global'.
I don't want to do this:
global['myConfig'] = { ... }
How do I either extend the Global
type to contain myConfig
or just tell TypeScript to shut up and trust me? I'd prefer the first one.
I don't want to change the declarations inside node.d.ts
. I saw this SO post and tried this:
declare module NodeJS {
interface Global {
myConfig: any
as a way to extend the existing Global
interface, but it doesn't seem to have any effect.
As of node@16
the NodeJS.Global
interface has been removed in favor of globalThis
.
You can declare new global variable in a module file as:
declare global {
var NEW_GLOBAL: string;
And in a non-module file (no top-level import/export) as:
declare var NEW_GLOBAL: string;
Important note: variable must be declared as var
. let
and const
variables don't show up on globalThis
.
–
–
Your file needs to be clean of any root level import
or exports
. That would turn the file into a module and disconnect it from the global type declaration namespace.
More : https://basarat.gitbooks.io/typescript/content/docs/project/modules.html
–
–
–
–
I suggest to define custom types. I do it under src/types/custom.d.ts
file in my project:
declare global {
namespace NodeJS {
interface Global {
myConfig: {
a: number;
b: number;
Then I ensure these are considered by Typescript in tsconfig.json
file:
"files": [
"src/types/custom.d.ts"
Now you're safe to use your custom property:
console.log(global.myConfig.a);
–
We're using "@types/node": "^7.0.18"
and TypeScript Version 2.3.4
. Our tsconfig.json file looks like this:
"compilerOptions": {
"module": "commonjs",
"target": "es6"
"exclude": [
"node_modules"
–
Use 'namespace' instead of 'module' to declare custom TypeScript
If you use any of the above answers and are using a newer version of Typescript you'll get a nag about using "module". You should consider namespace instead.
In order to satisfy the requirement here you'll actually need more than extending the Global interface. You'll also need to create a constant with the type as well if you want it to be accessible directly from the "globalThis" context.
NOTE: while the OP asked about an object literal the process is the same as you see here below. Rather than the "Debug" type being a function you would simply define the interface as need, then change "debug:" to myConfig or whatever you wish.
// typically I'll store the below in something like "typings.d.ts"
// this is because, at least typically, these overrides tend to
// be minimal in nature. You could break them up and Typescript
// will pick them up if you wish.
// Augmentations for the global scope can only be directly nested
// in external modules or ambient module declarations.
export {}
declare global {
// Definition or type for the function.
type Debug = (label: string) => (message: any, ...args: any[]) => void
// If defining an object you might do something like this
// interface IConfig { a: number, b: number }
// Extend the Global interface for the NodeJS namespace.
namespace NodeJS {
interface Global {
// Reference our above type,
// this allows global.debug to be used anywhere in our code.
debug: Debug
// This allows us to simply call debug('some_label')('some debug message')
// from anywhere in our code.
const debug: Debug
How the above might be used
For completeness in this example all we did was define a global so we can log a simple debug message. Here's how we'd bind the method to our global context.
global.debug = (label: string) => (message: any, ...args: any[]) => console.log(message, ...args)
We can also call our global debug method directly:
debug('express')(`${req.method}: ${req.url}`)
import Global = NodeJS.Global;
export interface CDTGlobal extends Global {
cdtProjectRoot: string
and then using it in other files like so
import {CDTGlobal} from "../lib/my.d.ts";
declare const global: CDTGlobal;
const cwd = global.cdtProjectRoot; // works
–
Only downside is when using it you will have to turn off the ESLint rule @typescript-eslint/no-namespace
.
For completeness here is my tsconfig.json
:
"compilerOptions": {
"declaration": true,
"emitDecoratorMetadata": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"jsx": "react",
"lib": ["dom", "es2017"],
"module": "commonjs",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"outDir": "dist",
"removeComments": true,
"resolveJsonModule": true,
"rootDir": "src",
"sourceMap": true,
"strict": true,
"target": "es6"
"exclude": ["dist", "node_modules"]
–
I can get both type check and code intelligence.
declare namespace NodeJS {
interface Global {
property: string
But interface Global
is point to global.GLOBAL
.
You can get correct type check, is because:
declare var global: NodeJS.Global & typeof globalThis;
But you can not get better code intelligence by useing global.property
, unless use global.GLOBAL.property
.
So, you need to define global var global
and extend interface Global
both:
// myglobal.d.ts
declare namespace NodeJS {
interface Global {
property: string
declare var global: NodeJS.Global & typeof globalThis
And now you can get property
intelligence when you type global.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.