作为函数且具有名称空间的模块的打字稿定义?

Typescript definition for a module that is a function and has namespaces?

我正在尝试为 react-grid-layout 制作一个 *.d.ts 文件。正如其 index.js 文件所示,它导出了一个函数 - React.Component 的一个子类,名为 ReactGridLayout:

// react-grid-layout/index.js
module.exports = require('./build/ReactGridLayout').default;
module.exports.utils = require('./build/utils');
// ...

要求:

var ReactGridLayout = require('react-grid-layout');
console.log(ReactGridLayout);
// --> function ReactGridLayout(props , context) { ...

它还会导出一些其他的东西,分成命名空间:

for (var f in ReactGridLayout) {
  if (ReactGridLayout.hasOwnProperty(f)) {
    console.log(f);
  }
}
// --> utils
// ...

因此它执行一次导出 多次导出。

我尝试了 Single Complex Object in Modules approach described on the Typescript site and this declaration file on GitHub 但没有成功。

更新

暂时忽略其他内容,我对 ReactGridLayout 的定义如下所示:

// react-grid-layout.d.ts
declare module 'react-grid-layout' {

  import * as React from 'react';

  export default class ReactGridLayout<P,S> extends React.Component<P,S> {

    containerHeight():void;

    onWidthChange(width:number):void;

   /* more methods here ... */

}

编译。然而它生成 Javascript 像:

var react_grid_layout_1 = require('react-grid-layout');

React.createElement(react_grid_layout_1.default, null, ...

应该是:

React.createElement(react_grid_layout_1, null, ...    

因为 react-grid-layout 正在导出 ReactGridLayout class "directly" 而不是 default 你不能做 export default (你已经看到发生了什么)。我认为您必须解决 export = 语法,但这似乎限制您只能导出一件事。解决这个问题的一种方法是利用 TypeScript 的声明合并。导出一个 class 和一个同名的命名空间。这或多或少是 react-grid-layout 正在做的事情。

main.tsx

import * as React from 'react'
import * as ReactGridLayout from 'react-grid-layout'

var grid = new ReactGridLayout(null, null);
var responsiveGrid = new ReactGridLayout.ResponsiveReactGridLayout(null, null);

<ReactGridLayout></ReactGridLayout>
//<ReactGridLayout.ResponsiveReactGridLayout></ReactGridLayout.ResponsiveReactGridLayout>

main.js(转译)

"use strict";
var React = require('react');
var ReactGridLayout = require('react-grid-layout');
var grid = new ReactGridLayout(null, null);
var responsiveGrid = new ReactGridLayout.ResponsiveReactGridLayout(null, null);
React.createElement(ReactGridLayout, null);
//<ReactGridLayout.ResponsiveReactGridLayout></ReactGridLayout.ResponsiveReactGridLayout>

types.d.ts

declare module 'react-grid-layout' {

    import * as React from 'react';

    class ReactGridLayout extends React.Component<ReactGridLayout.Props, ReactGridLayout.State> {
        // members
    }

    namespace ReactGridLayout {
        export interface State {
            activeDrag?: any; // declare LayoutItem, etc..
            // etc...
        }

        export interface Props {
            className?: string
            // etc...
        }

        export class ResponsiveReactGridLayout extends React.Component<any, any>
        {
            // etc
        }
    }

    export = ReactGridLayout;
}

顺便说一句:您可能会发现查看 react-grid-layout 的 ES6 代码更容易。