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

0yg35tkg  于 2022-11-26  发布在  TypeScript
关注(0)|答案(9)|浏览(233)

我尝试将现有项目转换为使用Typescript,但在测试设置中遇到问题。
我有一个用于测试的设置文件,它设置了jsdom,这样我所有的DOM交互代码都可以在测试期间正常工作。使用Typescript(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/');
zte4gxcn

zte4gxcn1#

原创答案,避免错误

将其放在 typescript 文件的顶部

const globalAny:any = global;

然后改用globalAny。

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

已更新答案以维护类型安全

如果要保持类型安全,可以扩充现有的NodeJS.Global类型定义。

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

请记住,类型脚本global的作用域与NodeJS接口Global不同,也与Global类型的名为global的节点global property不同...

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

vof42yt12#

除了其他答案外,你也可以直接在作业现场简单地castglobal

(global as any).myvar = myvar;
rjzwgtxy

rjzwgtxy3#

我通过执行以下操作解决了此问题...

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

declare var global: Global;
lrl1mhuk

lrl1mhuk4#

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

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

使用它:

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

rggaifut5#

避免类型转换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
}
qij5mzcb

qij5mzcb6#

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

xzv2uavs7#

一个简单的方法可以用来扩展Typescript“窗口”类型
步骤1:追加Windows对象

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

步骤2:声明

let foo = 'value of foo'

步骤3:添加到窗口对象

window.foo

window.foo = foo

为我工作。

kcrjzv8t

kcrjzv8t8#

如何在global中声明内容

1.创建global声明文件,例如:src/types/index.d.ts
1.将global声明文件添加到tsconfig.json

{
  "compilerOptions": {
    /* ... */
    "typeRoots": [
      "./src/types",
    ],
    /* ... */
  },
  /* ... */
}

从 typescript 文档

可以从模块内部向全局作用域添加声明
因此,例如,如果要向数组接口添加一些额外的内容,则需要执行以下操作:
observable.ts(示例)

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

声明变量以从global访问它们

如果要添加全局变量以用作global.myVariable,需要执行以下操作:
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
mzaanser

mzaanser9#

我用typescript创建了一个nodeJS应用程序,修复它的方法是更新devDependencies中的@types/node以匹配我使用的版本。

相关问题