如何在 TypeScript 中模仿私有和 public 构造函数重载
How to mimic private and public constructor overloads in TypeScript
我有一个 class 打算从两个不同的地方构建,在 class 外部和 class 内部。
定义 class 的模块提供了一个对象,class 在其闭包环境中捕获该对象。
从 class 内部(例如方法调用),class 是用对象构造的。
这是 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)
,但实际上,这并不能反映 class 的用途。
我认为最直观的答案是:
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 不允许这样做。
还有其他方法可以实现我想要做的事情吗?
虽然拥有多个具有不同可见性的 call/construct 签名会很好,但语言不支持。请参阅 microsoft/TypeScript#9592,它作为设计限制被关闭:它似乎不是一个足够常见的用例,不足以保证额外的工作和编译器的复杂性。
相反,我建议您考虑使用一组单独的面向外部和内部的接口,其中外部接口仅包含“public”功能,内部接口还包含“私有”功能。当您 export
您的 values/types 时,仅公开 public 功能:
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
class 的内部版本可以用两种方式构造,但是您将它导出为只有无参数 construct signature 的东西。因此阻止导入此库的其他代码使用“私有”构造函数:
import { T } from "./lib";
const t = new T(); // okay
t.create(); // okay
new T("something"); // error!
// ~~~~~~~~~~~ Expected 0 arguments, but got 1.ts
我有一个 class 打算从两个不同的地方构建,在 class 外部和 class 内部。
定义 class 的模块提供了一个对象,class 在其闭包环境中捕获该对象。
从 class 内部(例如方法调用),class 是用对象构造的。
这是 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)
,但实际上,这并不能反映 class 的用途。
我认为最直观的答案是:
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 不允许这样做。
还有其他方法可以实现我想要做的事情吗?
虽然拥有多个具有不同可见性的 call/construct 签名会很好,但语言不支持。请参阅 microsoft/TypeScript#9592,它作为设计限制被关闭:它似乎不是一个足够常见的用例,不足以保证额外的工作和编译器的复杂性。
相反,我建议您考虑使用一组单独的面向外部和内部的接口,其中外部接口仅包含“public”功能,内部接口还包含“私有”功能。当您 export
您的 values/types 时,仅公开 public 功能:
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
class 的内部版本可以用两种方式构造,但是您将它导出为只有无参数 construct signature 的东西。因此阻止导入此库的其他代码使用“私有”构造函数:
import { T } from "./lib";
const t = new T(); // okay
t.create(); // okay
new T("something"); // error!
// ~~~~~~~~~~~ Expected 0 arguments, but got 1.ts