在TypeScript环境模块中导出分配和导出类型

时间:2019-04-04 01:22:15

标签: typescript typescript-typings

我正在尝试为特定于我们应用的config模块添加类型。 config模块是从JSON文件动态生成的,因此键入起来很麻烦。由于它是节点模块,因此我使用ambient module进行输入。

// config.d.ts
declare module 'config' {
  interface AppConfig {
    name: string;
    app_specific_thing: string;
  }
  const config: AppConfig;
  export = config;
}

我还如何导出AppConfig,以便可以将其用作如下类型:

import * as config from 'config';

const appConfig: config.AppConfig;

尝试

  • 如果我直接在config模块中导出AppConfig,则会出现以下错误:

      

    TS2309:导出分配不能在具有其他导出元素的模块中使用。

  • 如果我将AppConfig移至另一个文件(例如./app_config)以保存导出并将其导入config.d.ts,则会出现以下错误:

      

    TS2439:环境模块声明中的导入或导出声明不能通过相对模块名称引用模块。

  • 如果我将AppConfig导出文件放在同一文件中,但在config模块之外,则会出现以下错误:

      

    TS2665:扩充中的模块名称无效。模块'config'解析为$ PROJ / config / lib / config.js上无法键入的模块,无法对其进行扩充。

这类似于Typescript error "An export assignment cannot be used in a module with other exported elements." while extending typescript definitions,但要求我希望能够直接将AppConfig作为类型导入其他TS文件中。

1 个答案:

答案 0 :(得分:0)

答案需要一个令人困惑的打字稿概念:

Declaration merging-编译器将两个用相同名称声明的独立声明合并为一个定义。在这种情况下,我们创建两个config的声明。

// config.d.ts
declare module 'config' {

  // This nested namespace 'config' will merge with the enclosing 
  // declared namespace 'config'.
  // https://www.typescriptlang.org/docs/handbook/declaration-merging.html
  namespace config {
    interface AppConfig {
      name: string;
      app_specific_thing: string;
      my_enum: FakeEnum;
    }

    interface MyInterface {}

    // See side note below
    type FakeEnum = 'A' | 'B' | 'C';
  }

  const config: AppConfig;
  export = config;
}

您可以像这样使用导入:

import * as config from 'config';
import { FakeEnum, MyInterface } from 'config';

请注意,您不能将enumsambient moduledeclare module 'config')一起使用,因为枚举会编译为JS对象,并且无法将新对象添加到模块中不要管您可以通过伪装具有联合类型的枚举来解决此问题:

type FakeEnum = 'A' | 'B' | 'C';