我正在为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中一样,任何包含顶级
import
或export
的文件都被视为一个模块。相反,没有任何顶级import
或export
声明的文件将被视为脚本,其内容在全局范围内可用(因此也适用于模块)。
by TypeScript Contributor Mohamed Hegazy提供了术语的进一步说明。
在导入后,声明对其他模块不再可用。也就是说,当我的文件缺少顶级导入/导出时,我只能使用类型React.ReactNativeScript
。否则,将出现以下错误:
命名空间'React'没有导出的成员'ReactNativeScript'。
注意:在我的tsconfig.json
上,这可能是不正确的配置,但是我已经尝试了tsconfig typeRoots
和package.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
设置如何,声明文件都是如果它是脚本而不是模块,则其他模块会注意到它。