列出 class 的私有 属性 名称

List private property names of the class

我需要使用 class 属性名称的某些子集作为映射中的值以在 class 内部使用。在下面的示例中,我用数组替换了地图。问题是,如果 属性 被标记为 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
}

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

Type '"x"' is not assignable to type '"y"'.

如您所见,class Cprivateprotected 属性不会作为 keyof C 的一部分出现。这通常是可取的行为,因为大多数使用 private/protected 属性 索引到 class 的尝试都会导致编译错误。有一个 suggestion to allow mapping 类型到 private/protected 属性为 public 的版本,这将为您提供一种执行此操作的方法......但是此功能尚未在 TypeScript 中实现3.5.

所以这行不通:

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

但也许您实际上并不需要 private 的属性,甚至对 class 的外部用户不可见。您可以使用 module/namespace 仅导出您想要的 class 方面,如下所示:

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

NotExported中,class构造函数_A和对应的类型_A没有直接导出。在内部,keyof _A 包含 "x""y" 键。我们导出的是一个构造函数 A 和一个相应的类型 A,它省略了 x 属性(和 keys 属性) 18=]。所以你得到了你想要的内部行为,而 NotExported.A 的外部行为与 Privates.A 的相似。 xkeys 不是由于 private 违规而无法访问,而是因为它们不是导出的 A 类型的一部分而无法访问。

我实际上更喜欢后一种不导出实现细节的方法,而不是暴露 private 属性的存在,因为 private 属性实际上对相应的 classes 可以使用。即private是访问控制,不是封装。

好的,希望对您有所帮助;祝你好运!

Link to code