列出类的私有属性名称

Qwe*_*tiy 6 private typescript keyof

我需要使用类属性名称的一些子集作为映射中的值以在类内部使用。在下面的示例中,我用数组替换了地图。问题是,如果属性被标记,private它不会在keyof列表中列出。如果我需要包含私有名称,如何指定密钥类型?

var keys: Array<keyof A> = ["x", "y"]; // Error

class A {
  private x = 7;
  public y = 8;

  private keys: Array<keyof A> = ["x", "y"]; // Error
}
Run Code Online (Sandbox Code Playgroud)

对于类外部的变量和类内部的私有属性都存在相同的错误:

类型“x”不可分配给类型“y”。

jca*_*alz 6

正如您所注意到的,privateprotected的属性C不会作为 的一部分出现keyof C。这通常是理想的行为,因为大多数尝试对具有私有/受保护属性的类进行索引都会导致编译错误。microsoft/TypeScript#22677有一项建议,允许将类型映射到私有/受保护属性为公共的版本,这将为您提供一种执行此操作的方法...但此功能自 TypeScript 4.9 起尚未实现。

所以这不起作用:

namespace Privates {
  export class A {
    private x: string = "a";
    public y: number = 1;
    private keys: Array<keyof A> = ["x", "y"]; // Error
  }
  var keys: Array<keyof A> = ["x", "y"]; // Error
}
const privateA = new Privates.A();
privateA.y; // number
privateA.x; // error: it's private
privateA.keys; // error: it's private
Run Code Online (Sandbox Code Playgroud)

但也许您实际上并不需要这些属性private,甚至不需要该类的外部用户可见。您可以使用模块/命名空间仅导出您想要的类的方面,如下所示:

namespace NotExported {
  class _A {
    x: string = "a";
    y: number = 1;
    keys: Array<keyof _A> = ["x", "y"]; // okay
  }
  export interface A extends Omit<_A, "x" | "keys"> {}
  export const A: new () => A = _A;
  var keys: Array<keyof _A> = ["x", "y"]; // okay
}

const notExportedA = new NotExported.A();
notExportedA.y; // number
notExportedA.x; // error: property does not exist
notExportedA.keys; // error: property does not exist
Run Code Online (Sandbox Code Playgroud)

在 中NotExported,类的构造函数_A和对应的类型_A并不是直接导出的。内部keyof _A包含"x""y"键。我们导出的是一个构造函数和A一个相应的类型A,该类型省略了. 这样你就得到了你想要的内部行为,而 的外部行为与 的类似。它们不是因为违规而无法访问,而是因为不属于导出的一部分而无法访问。xkeys_ANotExported.APrivates.AxkeysprivateA类型的一部分而无法访问。

实际上,我更喜欢后一种不导出实现细节的方法,而不是公开属性的存在private,因为private属性实际上对相应类的使用方式有很大影响。也就是说,private是关于访问控制,而不是关于封装。

链接到代码