54

i get this error whenever i try to add a function to the global nodejs global namsepace in a TypeScript environment.

Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature

declaring the global namespace

declare global {
  namespace NodeJS {
    interface Global {
      signin(): string[]
    }
  }
}

so if i try this

global.signin = () => {}

it returns a

Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature

brillout
  • 7,804
  • 11
  • 72
  • 84
Mhd
  • 817
  • 1
  • 8
  • 21
  • 13
    I was hoping for a proper answer to this exact question. Started getting this error while trying to upgrade to NextJS v11 with Webpack v5, only solution I have found was to install @types/node@15.12.2 as a dependency. Still looking for a better solution, but I found this info here if it helps. https://github.com/facebook/jest/issues/11640 – WebDevNewbie Jul 23 '21 at 18:06
  • 2
    `declare global` only works if it is included in the project, and there are a couple of ways to do that. Could you please tell me, in which file do you put `declare global`? Also, is it in the same file as `global.signin = () => {}` ? – Parzh from Ukraine Sep 13 '21 at 15:25
  • Oh no it’s not in the same file. Had it in another file in my project that was meant for jest setup. It doesn’t have to be in the same file to work because you’re targeting a global namespace which is meant to be available all through your codebase in the same parent folder. – Mhd Sep 19 '21 at 07:57
  • Maybe try using (global as any).signin = () => {} – CZTopp Aug 04 '23 at 07:35

12 Answers12

67

I was having a similar issue and I found that node's global typings were changed recently-ish; you can now override them by doing:

// global.d.ts
declare global {
    function someFunction(): string;
    var someVariable: string;
}

Note: this will not work with let or const you must use var.

// index.ts
global.someFunction = () => "some value";
global.someVariable = "some value";
IRONM00N
  • 1,105
  • 4
  • 17
  • 3
    I tried but TS says `Statements are not allowed in ambient contexts.`. – brillout Sep 18 '21 at 07:14
  • @brillout I edited my answer to make it more clear about what goes in each file – IRONM00N Sep 18 '21 at 21:27
  • 3
    Not working for me, the compiler still complains with the following message: 'Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature'. – Anthony Luzquiños Oct 18 '21 at 23:58
  • 4
    I needed to add `export {}` to `global.d.ts` to workaround _"Augmentations for the global scope can only be directly nested in external modules or ambient module declarations."_ . @AnthonyLuzquiños - I wonder if the compiler is aware of your global.d.ts file? I include it in tsconfig.json `{..., "include": ["src/**/*", "global.d.ts"]}`, hth – ptim Nov 25 '21 at 15:30
  • I worked, partially. VSCode error is now gone, but I'm still getting the same error when I try to run it. I have created a [project](https://github.com/AnthonyLzq/test-global), in case you want to give it a try. I'm using node 16.13.0, yarn 1.22.17 and my so is: 5.10.79-1-MANJARO. – Anthony Luzquiños Nov 25 '21 at 23:25
  • 1
    @AnthonyLuzquiños. I have the same issue. The VS Code error is gone, but I get ` error TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.` – Shamoon Dec 02 '21 at 22:37
  • 5
    Hi @Shamoon, I finally solve the issue, it was related to `ts-node`, this is a related [question](https://stackoverflow.com/questions/51610583/ts-node-ignores-d-ts-files-while-tsc-successfully-compiles-the-project) to that, I have also wrote a Medium article about it, [here](https://medium.com/@anthonylzq/how-to-create-global-variables-in-typescript-with-node-js-9ca24f648991) is it. – Anthony Luzquiños Dec 12 '21 at 21:02
  • 1
    Just like to add that I kept tripping up here as i had an the "no-var" ESLint rule however when using declare you must use var and not let or const as I found out. – Joss Bird Jan 16 '22 at 16:36
  • 2
    @JossBird I edited the answer to clear up any confusion for anyone else that stumbles across this. – IRONM00N Jan 17 '22 at 00:33
  • what's the reason that it works with `var`, but not with `let` or `const`? – Gernot Raudner Mar 02 '22 at 15:48
  • This works in node 16 – Jeremy John Sep 01 '22 at 16:21
  • Getting `TS2669: Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.` in node18 – Vadorequest Jan 09 '23 at 17:08
38

Below is an example for Node v16

// globals.d.ts
declare module globalThis {
    var signin: () => string[];
}
Willian Arana
  • 615
  • 8
  • 7
  • 3
    This seems to be the only answer anywhere on the internet that is up to date. Not sure how you knew this answer. My only caveat is it was auto-corrected by my editor to `declare namespace globalThis` – tettoffensive Mar 24 '22 at 03:46
  • 1
    I second @tettoffensive this is the only one that works in node v16 – destroyer22719 Apr 02 '22 at 14:43
  • where is this `globals.d.ts` supposed to be? do we need create it or is it already there – Circuit Planet Nov 13 '22 at 14:03
  • @CircuitPlanet you need create the file with name "globals.d.ts", the typescrit join the config because it is global, so you can create it in any folder of your application – Willian Arana Nov 14 '22 at 20:38
14

I had the same problem with a svelte.kit app. my database module use a global variable to store the dbClient as a promise. VSCode stop complain when the global.d.ts file had this content.

import type { MongoClient } from 'mongodb'

declare global {
  namespace globalThis {
    var _mongoClientPromise: Promise<MongoClient>
  }
}
Cool Lab
  • 209
  • 2
  • 5
11

You should declare a global declared as interface in global.d.ts like this:

export interface global {}
declare global {
  var signin: ()=>string[]
}

The vscode gives correct code hints

umuoy1
  • 111
  • 1
  • 2
7

You have to use the var keyword in declare global, and remove namespace NodeJS {.
Like this:

//globals.d.ts
import type { EventEmitter } from "events";
declare global {
    var myGlobal: EventEmitter;
}
/// <reference path="globals.d.ts" />
//index.ts
// reference needs to be at top of file
import { EventEmitter } from "events";
global.myGlobal = new EventEmitter();
global.myGlobal // EventEmitter type: EventEmitter
window.myGlobal // EventEmitter type: EventEmitter

Or if you don't have any imports in the .d.ts file:

//namedoesntmatter.d.ts
declare var a: string;
//index.ts
global.a = "Hello"
global.a //Hello type: string
window.a //Hello type: string
jackssrt
  • 364
  • 1
  • 2
  • 16
3

I too had the same issue. Fixed it by the below code.

declare global {
        function signin(): Promise<string[]>
}
jonathan
  • 33
  • 5
  • 5
    Your answer could be improved by adding more information on what the code does and how it helps the OP. – Tyler2P Dec 09 '21 at 20:41
3

This is how I solved with Node.js V16+

// global.d.ts

export declare global {
   declare module globalThis {
      var MyVar: object;
   }
}
passionateLearner
  • 722
  • 1
  • 7
  • 19
3

I tried everything I found here, but nothing worked.
Even stranger, VSCode showed NO TypeScript errors, but running tsc still threw:
TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.

After hours, I realised I forgot an "include": [ "src/app.ts" ] line in my tsconfig.json file.

Note to future self and for those who may have made the same mistake:
If you have explicitly provided one or more files in TypeScript's config with include, and that does not include the *.d.ts file, where you declared your globals, the build will fail with this error, even if VSCode shows no error (because it sees the global declaration, but TypeScript won't).

frzsombor
  • 2,274
  • 1
  • 22
  • 40
1

in my own case i didn't quite realize until later that the global namespace i declared was case sensitive.

instead of this. before my question was edited it was namespace NODEJS

declare global {
  namespace NODEJS {
    interface Global {
      signin(): string[]
    }
  }
}

it was supposed to be this

declare global {
  namespace NodeJS {
    interface Global {
      signin(): string[]
    }
  }
}

pay attention to NODEJS and NodeJS. After i made these changes, typescript was cool with it and it work the way i expected it to.

Mhd
  • 817
  • 1
  • 8
  • 21
0

just declare variable by var keyword. like this:

// eslint-disable-next-line no-var
var hello = () => { console.log("hello world"); };
// eslint-disable-next-line no-var
var hi: () => number;

globalThis.hello();
globalThis.hi = () => 143;

enter image description here

You can declare variables in .d.ts files, too.

enter image description here

0

This is work for me during connect db with next 13.4

declare global {
  var mongoose: { conn: any; promise: any };
}
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
0

Create the global.d.ts file and copy the following code:

declare global {
  declare module globalThis {
    var uniqueId: string;
  }
}

export {};

And finally, add "include": ["global.d.ts"] to the tsconfig.json file

Done!

Mohamad
  • 36
  • 4