带有多个文件中的模块的Typescript模块扩充

时间:2018-11-18 22:43:13

标签: typescript

过去,当来自的类型声明时,我已经成功使用了打字稿“模块扩充”作为临时解决方法 DefinitelyTyped落后于基础javascript库。类型定义始终包含在单个文件中,但是,我正在使用的特定公共库的新版本通过重新导出等方式将这些定义分为多个模块。

过去这是可行的,但现在不行了:

import * as Sequelize from 'sequelize';
declare module 'sequelize' {
  interface HasManyOptions {
    sourceKey?: string;
  }

那么如何使用以下文件结构向 HasManyOptions 界面添加 sourceKey ?我试过弄乱导入模块的名称和嵌套模块的声明,但是没有爱。我很困惑。


index.d.ts

export * from './lib/sequelize'

./ lib / sequelize.d.ts

export * from './associations/index'

./ lib / associations / index.d.ts

export * from './has-many'

./ lib / associations / has-many.d.ts

export interface HasManyOptions extends ManyToManyOptions {
    keyType?: DataType
    ...
}

2 个答案:

答案 0 :(得分:2)

感谢repro案@BillyB。您想要这个:

import { ManyToManyOptions, DataType } from 'sequelize'

declare module 'sequelize' {
  interface HasManyOptions extends ManyToManyOptions {
    /**
     * A string or a data type to represent the identifier in the table
     */
    keyType?: DataType
    sourceKey?: string
  }
}

模块扩充的文献资料还不够丰富。这是这样的:

  1. declare module 'sequelize',告诉TS您正在声明sequelize模块。名称合并在TS中的工作方式,TS会将具有确切路径'sequelize'的所有模块合并到一个模块中。
  2. 接口合并在TS中的工作方式,您的接口不仅必须具有相同的名称,而且它们的 entire声明必须相同(这包括extends子句和类型参数) 。因此,我们必须从源声明中复制keyType,这有点麻烦。

为此,我将在TypeScript的issue tracker中提交一个错误。令人惊讶的是,当您尝试声明一个与现有名称完全相同的接口作为扩展名时,TSC不会出错(忽略原始名称)。 TSC应该抛出一个异常,即您的模块导出两个同名的不相关接口,或者在执行接口合并时(至少在模块扩充的特定情况下),TS不应考虑extends子句。

答案 1 :(得分:1)

这在我的机器上正常工作:

sequelize.d.ts

import 'sequelize';

declare module 'sequelize' {
    interface ManyToManyOptions {
        sourceKey?: string;
    }
}

index.ts

import { ManyToManyOptions, AssociationOptions } from 'sequelize';

const options: AssociationOptions = {};

const optionsToo: ManyToManyOptions = {
    sourceKey: 'foo',
};

https://github.com/shaunluttin/typescript-module-augmentation-sequelize

编辑:这是BillyB的修复程序。

  

为将来的读者回顾一下,我的问题有两个部分的解决方案:在这些带有重新导出的声明的多文件情况下,出于某种原因,模块扩充需要放在单独的文件中;单个打字文件中不是这种情况。其次,如果要扩展扩展其他接口的接口,则必须重复声明的扩展部分;同样,仅使用一个键入文件就不需要这样做。