我有这个TypeScript + React + Webpack + Jest + Enzyme完全正常工作。
我认为需要在我的测试规范中访问一些全局功能。我可以通过将Jest配置中的setupTestFrameworkScriptFile
选项指向.js
文件来实现,我有类似这样的内容:
const Enzyme = require("enzyme");
const React = require("react");
const getMuiTheme = require("material-ui/styles/getMuiTheme").default;
global.mountWithContext = (node) => {
return Enzyme.mount(node, {
context: {
muiTheme: getMuiTheme()
},
childContextTypes: {
muiTheme: React.PropTypes.object
}
});
};
在我的spec文件中,我可以调用mountWithContext()
,当我运行测试时它会正常工作。但我的编辑不承认这个功能。
要解决这个问题,我已经创建了一个/typings/declarations.d.ts
文件:
declare function mountWithContext(node: any): any;
现在我的spec文件识别mountWithContext
函数,但类型是"错误"。正确的定义更像是这样的:
declare function mountWithContext(node: React.ReactElement<any>): Enzyme.ReactWrapper<P, S>;
React.ReactElement
已正确识别,因为@types/react/index.d.ts
文件包含以下内容:
export = React;
export as namespace React;
对酶来说同样如此。没有导出全局Enzyme
。看@types/enzyme/index.d.ts
那里有这样的事情:
export interface ReactWrapper<P, S> extends CommonWrapper<P, S> {
(...)
}
但即使我这样做:
declare function mountWithContext(node: React.ReactElement<any>): ReactWrapper<P, S>;
它不起作用。 ReactWrapper
仍然无法识别。
我尝试在这个declarations.d.ts
文件中导入,这将允许我正确使用该类型,但我的函数声明将停止在我的spec文件中被识别。我还尝试添加这样的三重斜杠指令:
/// <reference path="../node_modules/@types/enzyme/index.d.ts" />
该文件已被识别,但ReactWrapper
类型仍然没有。
所以...我如何为我的自定义mountWithContext
全局函数提供TypeScript函数声明,其中包含所有正确的类型,如下所示:
declare function mountWithContext(node: React.ReactElement<any>): ReactWrapper<P, S>;
答案 0 :(得分:5)
如果我们要声明global.mountWithContext
函数存在并且具有指示的类型,我们可以将以下内容添加到项目中的空声明文件中。
import React from 'react';
import enzyme from 'enzyme';
declare global {
namespace NodeJS {
interface Global {
mountWithContext<P, S>(node: React.ReactElement<any>): enzyme.ReactWrapper<P, S>;
}
}
}
<强>详情
以下是上述每个结构的细分:
declare global
块:此构造的目的是通过引入新声明或修改现有声明来修改(如果愿意,扩充)全局范围,来自 非全局上下文,例如模块。我们的声明文件是一个模块,因为它包含从Enzyme导入import
的顶级ReactWrapper
子句。
这样的块被称为&#34;全局增强&#34;并且也可能出现在实现文件中。
interface Global
结构中包含的namespace NodeJS
:在我们的测试中,我们作为全局变量的成员访问mountWithContext
函数,偶然命名为global
,这是由Node环境提供的。此变量已由Node的类型声明声明,与其他环境全局变量(如process
)处于同一级别。但是,我们需要通过添加新成员来扩充其类型。此全局global
的类型是已在interface
Global
内声明的namespace
NodeJS
,由Node的官方声明。我们通过声明interface
Global
的新成员来实现此目的。我们的扩充需要包含在包含namespace
的{{1}}中,否则它将被视为单独的Global
。粗略地说,词法范围适用。 (回想一下,TypeScript接口可以在同一范围内多次声明,并且这些声明将被合并)
备注强>
我们在哪里发布此声明? 任何会导致TypeScript获取它并将其包含在我们的编译上下文中的地方。 按照惯例,我们将它放在项目根目录中名为 globals.d.ts 的文件中。 (从技术上讲,它可以被命名为其他东西并进入较低的目录。)
请务必注意,此声明文件是我们的应用程序代码的一部分,应该检查到源代码管理中。 必须 不 与第三方声明一起放在 typings , node_modules / @ types 等目录中,或者<强> jspm_packages / NPM / @类型强>
同样重要的是要注意,此扩充仅影响TypeScript文件(interface
,.ts
,.tsx
)。如果我们在使用TypeScript语言服务时声明这个函数只是为了在.d.ts
或.js
文件中工作时提供智能感知,那么这种方法将不起作用。
答案 1 :(得分:0)
函数签名错误,您必须先声明泛型类型,例如:
function foo(T: bar): T // wrong
function foo<T>(T: bar): T // right
function foo<T extends K, K>(T: bar): K // right
在你的情况下,这样的事情应该有效:
declare function mountWithContext<P, S>(node: React.ReactElement<any>): ReactWrapper<P, S>;
如果您碰巧知道P
和S
的内容,则可以使用<P extends React.Component, K>
更具体,例如。