键入使用静态方法导出函数构造函数的CommonJS模块

时间:2018-04-15 00:29:52

标签: typescript typescript-typings

我正在尝试为minimal-bit-array创建声明文件。这就是它的本质:

function A() { this.data = 'foo'; }

A.prototype.serialize = function() { /* ... */ };

module.exports = A;
module.exports.deserialize = function(x) { /* ... */ };

如何输入?

1 个答案:

答案 0 :(得分:4)

这是:

declare module "a" {
  namespace A {
    export interface X { /* ... */ }
  }

  interface A {
    data: string;
    serialize(): A.X;
  }

  const A: {
    new (): A;
    deserialize(obj: A.X): A;
  };

  export = A;
}

这种反直觉的namespace + interface + const三明治成功合并为TypeScript可以理解的明确的 something 。消费示例:

import * as A from "a";

const a: A         = new A();
const d: A['data'] = a.data;
const x: A.X       = a.serialize();
const amazing      = A.deserialize(x);

为什么三明治?

从理论上讲,namespace Aconst A正在做同样的事情:描述module.exports的{​​{1}}。但构造函数 - a - 只能在接口中声明,而TypeScript唯一的东西 - new (): A - 只能在命名空间中定义。这就是为什么两者同时需要的原因。否则无法导出interface X。至少据我所知。值得庆幸的是,TypeScript知道如何合并它们。

同时,interface X只是一种便利。当在期望类型的上下文中的代码中的某处引用interface A时,这就是您获得的接口。另外两个 - Anamespace - 不是类型,所以没有歧义。可以将其保留在const中,但是,如果这太神奇了,请将其引用为namespace A

在2.8上测试。

更新

稍微清洁的方法:

A.A

类很适合这种情况。这在语义上也等同于原始方法,因为类在函数之上基本上是语法糖。检查this playground以查看上述类的实现将被转换为什么。

在2.8上测试。