How to prevent "Property '...' does not exist on type 'Global'" with jsdom and typescript?

fahrradflucht picture fahrradflucht · Nov 22, 2016 · Viewed 48.1k times · Source

I try to convert an existing project to use Typescript and I have problems doing so with my testing setup.

I had a setup file for my tests that sets up jsdom so that all my DOM interacting code works during my tests. Using Typescript (ts-node with mocha) I always get errors like this:

Property 'window' does not exist on type 'Global'.

To prevent this I tried patching the NodeJS.Global interface like this:

declare namespace NodeJS{
  interface Global {
    document: Document;
    window: Window;
    navigator: Navigator;
  }
}

But this didn't change anything.

How do I enable those browser properties on the NodeJS global variable?

Extras:

This is my mocha setup.ts:

import { jsdom, changeURL } from 'jsdom';

const exposedProperties = ['window', 'navigator', 'document'];

global.document = jsdom('');
global.window = global.document.defaultView;
Object.keys(global.document.defaultView).forEach((property) => {
  if (typeof global[property] === 'undefined') {
    exposedProperties.push(property);
    global[property] = global.document.defaultView[property];
  }
});

global.navigator = {
  userAgent: 'node.js',
};

changeURL(global.window, 'http://example.com/');

Answer

Steven Spungin picture Steven Spungin · Feb 17, 2017

Original Answer To Avoid Error

Put this at the top of your typescript file

const globalAny:any = global;

Then use globalAny instead.

globalAny.document = jsdom('');
globalAny.window = global.document.defaultView;

Updated Answer To Maintain Type Safety

If you want to keep your type safety, you can augment the existing NodeJS.Global type definition.

You need to put your definition inside the global scope declare global {...}

Keep in mind that the typescript global scope is not the same as the NodeJS interface Global, or the node global property called global of type Global...

declare global {
  namespace NodeJS {
    interface Global {
       document: Document;
       window: Window;
       navigator: Navigator;
    } 
  }
}