如何使用 jsdom 和类型脚本防止“ Property”... 在类型“ Global”上不存在?

我试图将一个现有的项目转换为使用 Typecript,但是我的测试设置在这样做时遇到了问题。

我有一个测试的安装文件,它设置了 jsdom,这样我的所有 DOM 交互代码在测试期间都能正常工作。使用类型脚本(ts-node with mocha)我总是会得到这样的错误:

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

为了防止这种情况,我尝试像下面这样修补 NodeJS.Global 接口:

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

但这改变不了什么。

如何在 NodeJS 全局变量上启用这些浏览器属性?

附加:

这是我的摩卡:

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/');
76487 次浏览

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;
}
}
}
declare namespace NodeJS {
export interface Global { window: any;
}
}

I fixed this problem by doing this...

export interface Global {
document: Document;
window: Window;
}


declare var global: Global;

In addition to other answers, you can also simply cast global directly at the assignment site:

(global as any).myvar = myvar;

Avoid typecasting any, it removes the purpose of typings. Instead install the type definitions needed (e.g. yarn add --dev @types/jsdom @types/node) and import to use:

import { DOMWindow, JSDOM } from 'jsdom'


interface Global extends NodeJS.Global {
window: DOMWindow,
document: Document,
navigator: {
userAgent: string
}
}


const globalNode: Global = {
window: window,
document: window.document,
navigator: {
userAgent: 'node.js',
},
...global
}

This is the right solution, not using Typescript's namespaces. It is also compatible with all eslint default rules:

// Declare a type.
interface CustomNodeJsGlobal extends NodeJS.Global {
myExtraGlobalVariable: number;
// You can declare anything you need.
}

Use it:

// Tell Typescript to use this type on the globally scoped `global` variable.
declare const global: CustomNodeJsGlobal;


function doSomething() {
// Use it freely
global.myExtraGlobalVariable = 5;
}


doSomething();

A simple method can be use extend the Typescript "Window" type

step 1: append Window object

interface Window {
foo:string // any type of your foo property
}

step 2: declare

let foo = 'value of foo'

step 3: add to window object

window.foo

or

window.foo = foo

work for me...

How to declare something in global

  1. Create global declaration file, for example: src/types/index.d.ts
  2. Add your global declaration file to tsconfig.json:
{
"compilerOptions": {
/* ... */
"typeRoots": [
"./src/types",
],
/* ... */
},
/* ... */
}

From Typescript Documentation

You can add declarations to the global scope from inside a module

So, for example, if you want to add something extra to the array interface, you need to do:

observable.ts (example)

// observable.ts
export class Observable<T> {
// ... still no implementation ...
}

src/types/index.d.ts

declare global {
interface Array<T> {
toObservable(): Observable<T>;
}
}

someWhereInApp.ts

Array.prototype.toObservable = function () {
// ...
};

Declaring variables to access them from global

If you want to add a global variable to use as global.myVariable you need to do:

src/types/index.d.ts

/* eslint-disable no-var */
declare global {
/*  ↓↓↓ "var" is important  */
var myVariable: string[];
}
/* eslint-enable no-var */

someWhereInApp.ts

const { myVariable } = global

I was creating a nodeJS application with typescript and what fixed it for me was updating the @types/node in devDependencies to match the version I was using.