键入一个使用静态方法导出函数构造函数的 CommonJS 模块
Typing a CommonJS module that exports a function constructor with static methods
我正在尝试为 minimal-bit-array
创建声明文件。这是它的本质:
function A() { this.data = 'foo'; }
A.prototype.serialize = function() { /* ... */ };
module.exports = A;
module.exports.deserialize = function(x) { /* ... */ };
我该如何输入?
是这样的:
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 可以理解的明确 东西 中。消费示例:
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 A
和const A
在做同样的事情:描述a
的module.exports
。但是构造函数 - new (): A
- 只能在接口中声明,而 TypeScript-only 的东西 - interface X
- 只能在命名空间中定义。这就是同时需要两者的原因。否则无法导出 interface X
。至少据我所知。值得庆幸的是,TypeScript 知道如何合并它们。
与此同时,interface A
只是一个方便。当在需要类型的上下文中的代码中某处引用 A
时,这就是您获得的接口。另外两个 - namespace
和 const
- 不是类型,所以没有歧义。可以将其保留在 namespace A
中,但是,如果这太神奇了,请将其引用为 A.A
.
在 2.8 上测试。
更新
一种更简洁的方法:
declare module "a" {
namespace A {
export interface X { /* ... */ }
}
class A {
static deserialize(obj: A.X): A;
data: string;
constructor();
serialize(): A.X;
}
export = A;
}
类 正好适合这种情况。这在语义上也等同于原始方法,因为 classes 本质上是函数之上的语法糖。检查 this playground 以查看上述 class 的实现将被转换成什么。
在 2.8 上测试。
我正在尝试为 minimal-bit-array
创建声明文件。这是它的本质:
function A() { this.data = 'foo'; }
A.prototype.serialize = function() { /* ... */ };
module.exports = A;
module.exports.deserialize = function(x) { /* ... */ };
我该如何输入?
是这样的:
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 可以理解的明确 东西 中。消费示例:
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 A
和const A
在做同样的事情:描述a
的module.exports
。但是构造函数 - new (): A
- 只能在接口中声明,而 TypeScript-only 的东西 - interface X
- 只能在命名空间中定义。这就是同时需要两者的原因。否则无法导出 interface X
。至少据我所知。值得庆幸的是,TypeScript 知道如何合并它们。
与此同时,interface A
只是一个方便。当在需要类型的上下文中的代码中某处引用 A
时,这就是您获得的接口。另外两个 - namespace
和 const
- 不是类型,所以没有歧义。可以将其保留在 namespace A
中,但是,如果这太神奇了,请将其引用为 A.A
.
在 2.8 上测试。
更新
一种更简洁的方法:
declare module "a" {
namespace A {
export interface X { /* ... */ }
}
class A {
static deserialize(obj: A.X): A;
data: string;
constructor();
serialize(): A.X;
}
export = A;
}
类 正好适合这种情况。这在语义上也等同于原始方法,因为 classes 本质上是函数之上的语法糖。检查 this playground 以查看上述 class 的实现将被转换成什么。
在 2.8 上测试。