如何使用 jsdom 和 typescript 防止“属性 '...' 不存在于类型 'Global'”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40743131/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:29:09  来源:igfitidea点击:

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

typescriptjsdomtypescript2.0

提问by fahrradflucht

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

我尝试将现有项目转换为使用 Typescript,但在我的测试设置中遇到了问题。

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:

我有一个用于我的测试的设置文件,它设置了 jsdom,以便我所有的 DOM 交互代码在我的测试期间工作。使用 Typescript (ts-node with mocha) 我总是得到这样的错误:

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

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

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

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?

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

Extras:

附加功能:

This is my mocha setup.ts:

这是我的摩卡咖啡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/');

回答by Steven Spungin

Original Answer To Avoid Error

避免错误的原始答案

Put this at the top of your typescript file

把它放在打字稿文件的顶部

const globalAny:any = global;

Then use globalAny instead.

然后改用 globalAny。

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.Globaltype definition.

如果你想保持你的类型安全,你可以增加现有的NodeJS.Global类型定义。

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

您需要将您的定义放在全局范围内 declare global {...}

Keep in mind that the typescript globalscope is not the same as the NodeJS interface Global, or the node global propertycalled globalof type Global...

请记住,打字稿global范围是不一样的界面的NodeJS Global,或节点global property称为global类型的Global...

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

回答by lleaff

In addition to other answers, you can also simply castglobaldirectly at the assignment site:

除了其他答案之外,您还可以直接在作业现场进行投射global

(global as any).myvar = myvar;

回答by Shawn

I fixed this problem by doing this...

我通过这样做解决了这个问题......

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

declare var global: Global;

回答by willsquire

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:

避免 typecasting any,它消除了打字的目的。而是安装所需的类型定义(例如yarn add --dev @types/jsdom @types/node)并导入以使用:

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
}

回答by Oleg Mikhailenko

declare namespace NodeJS {
  export interface Global { window: any;
  }
}

回答by José Cabo

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

这是正确的解决方案,而不是使用 Typescript 的命名空间。它还兼容所有 eslint 默认规则:

// 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();