【问题标题】:List private property names of the class列出类的私有属性名称
【发布时间】:2019-11-25 17:00:58
【问题描述】:

我需要使用类属性名称的一些子集作为映射中的值,以便在类内部使用。在以下示例中,我已将 map 替换为数组。问题是,如果属性标记为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
}

类外的变量和类内的私有属性都存在同样的错误:

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

【问题讨论】:

  • privateprotected 属性很难以编程方式处理,因为正如您所注意到的,它们不会出现在 keyof 中。您可能会考虑根本不将x 设为私有,而是导出一个省略xA 版本。但这取决于你的用例,我不知道。
  • 比较this...
  • ...到this。这能满足你的需求吗?如果是这样,我会回答;否则答案可能只是“不,你不能这样做,对不起”
  • @jcalz,有趣的想法。我认为您可以将其发布为答案。

标签: typescript private keyof


【解决方案1】:

如您所见,C 类的privateprotected 属性不会作为keyof C 的一部分出现。这通常是可取的行为,因为大多数尝试对具有私有/受保护属性的类进行索引都会导致编译错误。有一个 suggestion 允许 mapping 将类型转换为私有/受保护属性是公共的版本,这将为您提供一种方法来执行此操作...但是从 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,因为该类的外部用户不可见。您可以使用模块/命名空间仅导出您想要的类的方面,如下所示:

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

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

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

Link to code

【讨论】:

    猜你喜欢
    • 2013-01-18
    • 1970-01-01
    • 2017-08-13
    • 2014-06-27
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 2014-07-21
    • 1970-01-01
    相关资源
    最近更新 更多