typescript - 如何在 TypeScript 中模拟私有和公共构造函数重载
问题描述
我有一个旨在从两个不同的地方构建的类,即类外和类内。
定义类的模块提供了一个对象,该类在其闭包环境中捕获该对象。
从类内部(例如方法调用),类是用对象构造的。
下面是它在 JavaScript 中的样子:
const private_accessor = ...;
export class T {
create() {
return new T(private_accessor);
}
constructor(key) {
if (key === private_accessor) {
// trusted call
} else {
// outside callee
}
}
}
我们可以将构造函数键入为constructor(key?: object)
,但实际上,这并不能反映该类的使用方式。
我认为直观的答案是:
const private_accessor: object_type = ...;
export class T {
create(): T {
return new T(private_accessor);
}
private constructor(key: object_type);
public constructor();
constructor(key /* object_type? */) {
if (key === private_accessor) {
// trusted call
} else {
// outside callee
}
}
}
由于私有重载是一个实现细节,并且无论如何都不会在外部被调用者中工作,因此没有理由公开类型重载。
但是TSC不允许这样做。
还有另一种方法可以实现我想要做的事情吗?
解决方案
虽然拥有多个具有不同可见性的调用/构造签名会很好,但这只是语言不支持的。请参阅作为设计限制关闭的microsoft/TypeScript#9592:它似乎不是一个足够常见的用例来保证额外的努力和编译器的复杂性。
相反,我建议您考虑拥有一组单独的面向外部和面向内部的接口,其中外部接口仅包含“公共”功能,而内部接口还包含“私有”功能。当您export
的值/类型时,仅公开公共功能:
class T {
create(): T {
return new T(private_accessor);
}
constructor(key?: object_type) {
if (key === private_accessor) {
// trusted call
} else {
// outside callee
}
}
}
// public version of T
const Tpublic: new () => T = T;
export { Tpublic as T }; // renamed
在这里,类的内部版本T
可以两种方式构造,但是您将其导出为仅具有无参数构造签名的东西。因此,导入此库的其他代码无法使用“私有”构造函数:
import { T } from "./lib";
const t = new T(); // okay
t.create(); // okay
new T("something"); // error!
// ~~~~~~~~~~~ Expected 0 arguments, but got 1.ts
推荐阅读
- javascript - 使用Jquery计算两个日期之间的月差和半月差
- android - 添加flutter_email_sender插件后flutter无法编译
- sql - 单行子查询返回多行 - Case 语句
- excel - VBA:在用户窗体中收集和显示错误消息?
- r - 如何在 R 或 RMarkdown 中为每个单独导出的 PDF 报告添加文本?
- javascript - 选择后将标签滚动到中心?
- qt - 如何在 QML 中使用指定的行号和列号在表格视图中设置单元格项目的焦点?
- javascript - 如何使用 Filepond 制作缩略图以及正常大小的上传
- c# - 如何停止等待 Webdriver 直到页面加载完成,因为页面在 VPN 连接中需要大约 3 分钟才能完成?
- php - PHP - 09:00“下个月的第一天”的时间戳