具有来自外部模块的类型的增强模块声明

时间:2019-04-14 13:09:29

标签: reactjs typescript typescript-typings definitelytyped

上下文

我正在为NativeScript(即一个允许您使用React声明NativeScript UI的库)制作一个React渲染器,我想为其提供类型。

React的类型已经完全支持React DOM(即,到处都有对HTMLElements的引用),但是我需要增加类型以使它们也了解NativeScript元素。为了提供准确的输入,我需要提供对外部模块的引用,例如通过导入ActionBar。我的尝试看起来像这样(可以进行编译,但是我项目中的其他模块没有采纳):

// react-nativescript/index.d.ts
import { ActionBar } from "tns-core-modules/ui/action-bar/action-bar";

declare namespace JSX {
    interface IntrinsicElements {
        actionBar: React.ClassAttributes<ActionBar>
          & React.NativeScriptAttributes<ActionBar>
    }
}

declare namespace React {
    interface NativeScriptAttributes<T> {
        className?: string;
        children?: ReactNode;
        onClick?: MouseEventHandler<T>;
    }

// Omitting DetailedNativeScriptFactory<P, T> for brevity.
    interface ReactNativeScript {
        actionBar: DetailedNativeScriptFactory<
            NativeScriptAttributes<ActionBar>,
            ActionBar
        >,
    }
}

问题的根源

添加顶级导入ActionBar changes the file from a 'script' to a 'module'

  

在TypeScript中,就像在ECMAScript 2015中一样,任何包含顶级importexport的文件都被视为一个模块。相反,没有任何顶级importexport声明的文件将被视为脚本,其内容在全局范围内可用(因此也适用于模块)。

by TypeScript Contributor Mohamed Hegazy提供了术语的进一步说明。

在导入后,声明对其他模块不再可用。也就是说,当我的文件缺少顶级导入/导出时,我只能使用类型React.ReactNativeScript。否则,将出现以下错误:

  

命名空间'React'没有导出的成员'ReactNativeScript'。

注意:在我的tsconfig.json上,这可能是不正确的配置,但是我已经尝试了tsconfig typeRootspackage.json { {1}}至此,一切都没有改变。

(失败)替代方法

为了使声明可用于其他模块,我们可以尝试将types导入移动到名称空间本身中,例如:

ActionBar

但是,这引入了另一个编译错误:

  

名称空间中的导入声明无法引用模块

...更不用说我不想深入探讨的其他数百个由此引起的编译器错误。

已知问题?

我发现了这个看似相关的问题:https://github.com/Microsoft/TypeScript/issues/4166

  

我们今天的当前答案是“将您的内容移动到另一个// react-nativescript/index.d.ts declare namespace JSX { import { ActionBar } from "tns-core-modules/ui/action-bar/action-bar"; import { ClassAttributes, NativeScriptAttributes } from "react"; interface IntrinsicElements { actionBar: ClassAttributes<ActionBar> & NativeScriptAttributes<ActionBar> } } 文件中”。这是可以的解决方法,但效果不佳。真正的标贴是在外部模块中定义了一个类型时,即使这确实发生,也无法使用这些类型来扩展全局接口。之所以变得更加棘手,是因为这会鼓励人们在不想一开始就将类型移动到全局名称空间中,从而加剧了问题。

我真的不知道“将您的内容移动到另一个.d.ts文件”是什么意思。我开始尝试声明我在全局范围内所需的所有内容(本质上是为NativeScript构建一个.d.ts),但是NativeScript太大了而无法采用这种方法-如果他们更新其类型,那将是一场噩梦。 >

问题

如何通过引用外部模块(例如lib.dom.d.ts)来增强React的类型?

如果只有TypeScript将该文件公开给库中的所有其他文件(以及使用该文件的所有项目),看来我的初始方法将起作用,但是无论我的tns-core-modules设置如何,声明文件都是如果它是脚本而不是模块,则其他模块会注意到它。

0 个答案:

没有答案