如何处理打字稿定义文件中的类型名称冲突

How to deal with type name conflicts in a typescript definition file

我正在尝试为已经存在的库编写打字稿定义文件。这个图书馆 (react-filepond) exports an object called File (as can be seen in the usage example in the README).

问题是这个库创建的另一个接口利用了 JS File interface.

所以现在在我的打字稿定义文件中,我必须以某种方式管理类型 File 的两个定义。我对此的解决方案是在我的定义文件中将库创建的对象声明为不同的名称,并将其简单地导出为“文件”。

declare class FilePondFile extends React.Component<FilePondFileProps> { }
export { FilePondFile as File };

当我在自己的项目中使用该类型时,这看起来不错。但作为 OSS 的支持者,我想通过 Definitely Typed 存储库将此定义提供给社区。

他们的 linter 给了我一个错误,尽管这显然阻止了 my PR 被审查:

Error: C:/dev/DefinitelyTyped/types/react-filepond/index.d.ts:22:1
ERROR: 22:1   strict-export-declare-modifiers  'declare' keyword is redundant here. 
See: https://github.com/Microsoft/dtslint/blob/master/docs/strict-export-declare-modifiers.md

乍一看,删除 class FilePondFile 前面的 declare 似乎很简单,但是,如果删除它,我会得到一个不同的错误:

A 'declare' modifier is required for a top level declaration in a .d.ts file. 

所以我不确定如何处理这个矛盾。 Definitely Typed 的维护者似乎没有时间提供帮助,因为我的 PR 只是被标记为“需要作者注意”,尽管我已经清楚地解决了这个问题。

有没有人建议我可以做些什么来避免在此定义文件中复制对 File 的引用,同时还传递 Definitely Typed linter?

此错误信息:

A 'declare' modifier is required for a top level declaration in a .d.ts file.

声明文件不导出任何内容时显示。 declare 关键字是多余的,因为它已经在 *.d.ts 文件中假定。

拥有声明文件的目的是准确描述相应的 JavaScript 模块中正在发生的事情。 At the time of writing this postreact-filepond 包含 3 个命名导出:const registerPluginclass FilePondclass File。这意味着您的声明可能如下所示:

types/react-filepond/index.d.ts

import * as React from 'react';
import { registerPlugin } from 'filepond';

export { registerPlugin };

interface Props { /* FilePond props here */ }

export class FilePond extends React.Component<Props> { }

export class File extends React.Component { }

因为这就是模块中真正发生的事情。注意:如果 filepond 的类型不存在,最好首先为该库创建类型。

如果消费者遇到命名冲突,他们的职责是在本地提供别名:

import { File as FileComponent } from 'react-filepond';

由于每个人都有不同的设置,运行 冲突是您(作为打字作者)无法避免的。库作者避免这样的名称是一个好习惯,但如果他们不这样做,类型定义应该尊重他们的选择。

The problem with that is that another one of the interfaces that this library creates utilizes the JS File interface.

还有一个解决方案。

File 名称由从该模块声明和导出的 class 取用。

您必须在同一个模块中描述 FilePondItem 接口,并且它必须具有 file 属性 和 File 不同的类型 - 它必须引用一个在 lib.dom.d.ts

中定义的全局 File 对象
export interface FilePondItem {
    file: File;

TypeScript 类型是结构化的。您不必通过名称引用全局 File 类型,您可以提供其定义,与 lib.dom.d.ts:

中的定义兼容
export interface FilePondItem {
    file: Blob & {readonly lastModified: number; readonly name: string};

只要类型定义保持兼容,一切都会好起来的。

当然也有缺点:它是重复的代码,比较冗长,并且如果全局 File 类型发生变化,将来它有可能与实际的 File 不兼容(但我认为这不太可能)。