如何将其他类型导入到我的TypeScript自定义声明文件中?

Ric*_*ral 10 typescript reactjs jestjs enzyme typescript-typings

我有这个TypeScript + React + Webpack + Jest + Enzyme完全正常工作.

我认为需要在我的测试规范中访问一些全局功能.我可以通过将setupTestFrameworkScriptFileJest配置中的选项指向.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
        }
    });
};
Run Code Online (Sandbox Code Playgroud)

在我可以调用的spec文件中mountWithContext(),当我运行测试时它会正常工作.但我的编辑不承认这个功能.

为了解决这个问题,我/typings/declarations.d.ts用这个创建了一个文件:

declare function mountWithContext(node: any): any;
Run Code Online (Sandbox Code Playgroud)

现在我的spec文件识别该mountWithContext函数,但类型是"错误的".正确的定义更像是这样的:

declare function mountWithContext(node: React.ReactElement<any>): Enzyme.ReactWrapper<P, S>;
Run Code Online (Sandbox Code Playgroud)

React.ReactElement被正确识别,因为@types/react/index.d.ts文件包括这样的:

export = React;
export as namespace React;
Run Code Online (Sandbox Code Playgroud)

酶的情况也是如此.没有全球Enzyme出口.看着@types/enzyme/index.d.ts这样的事情:

export interface ReactWrapper<P, S> extends CommonWrapper<P, S> {
    (...)
}
Run Code Online (Sandbox Code Playgroud)

但即使我这样做:

declare function mountWithContext(node: React.ReactElement<any>): ReactWrapper<P, S>;
Run Code Online (Sandbox Code Playgroud)

它不起作用.ReactWrapper仍然没有得到认可.

我试图在这个declarations.d.ts文件中导入,这将允许我正确使用该类型,但我的函数声明将停止在我的spec文件中被识别.我也试过添加这样的三斜杠指令:

/// <reference path="../node_modules/@types/enzyme/index.d.ts" />
Run Code Online (Sandbox Code Playgroud)

并且文件被识别,但ReactWrapper类型仍然没有.

那么......我怎样才能为我的自定义mountWithContext全局函数提供一个TypeScript函数声明,其中包含所有正确的类型,如下所示:

declare function mountWithContext(node: React.ReactElement<any>): ReactWrapper<P, S>;
Run Code Online (Sandbox Code Playgroud)

Alu*_*dad 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>;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

细节

这是上面每个构造的分解:

  1. declare global块:该构建体的目的是修改,如果你愿意以增强,全球范围内,或者通过引入新的声明或通过修改现有的,从的非全局上下文诸如模块。我们的声明文件是一个模块,因为它包含从Enzyme import导入的顶层子句ReactWrapper。这样的块称为“全局增强”,也可能出现在实现文件中。

  2. 结构的interface Global包装namespace NodeJS:在我们的测试中,我们将访问mountWithContext函数作为global由Node环境提供的全局变量的成员,该变量的名称为。Node的类型声明已经在与其他环境全局变量(例如)相同的级别上声明了此变量process。但是,我们需要通过添加新成员来增加其type。全局的类型global是Node的官方声明中interface Global已经在中namespace NodeJS声明的。我们通过声明的新成员来完成此操作 interface Global。我们的扩充功能必须包装在namespace容器中Global,否则将被认为是单独的interface。粗略地说,词汇作用域适用。(回想一下,可以在同一作用域中多次声明TypeScript接口,并且这些声明将被合并)

笔记

我们在哪里放置此声明?任何会导致TypeScript拾取它并将其包含在我们的编译上下文中的地方。按照惯例,我们将其放置在项目根目录下的名为globals.d.ts的文件中。(从技术上讲,可以将其命名为其他名称,然后放在较低的目录中)。

重要的是要注意,此声明文件是我们的应用程序代码的一部分,应检查到源代码管理中。它必须不能在目录中放置旁边第三方声明,如分型node_modules / @类型,或jspm_packages / NPM / @类型

这也是要注意的重要,这增强影响打字稿文件(.ts.tsx.d.ts)只。如果我们只是想让TypeScript语言服务使用此功能只是为了在处理文件.js.jsx,文件时提供智能感知,则此方法将行不通。