列出类的私有属性名称 [英] List private property names of the class

查看:32
本文介绍了列出类的私有属性名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to use some subset of class properties names as values in a map to use inside of the class. In following example I've replaced map by array. The problem is that if property is marked private it's not listed in keyof list. How can I specify type of keys if I need to include private names?

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

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

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

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

There is the same error both for variable outside of the class and for private property inside of it:

类型 '"x"' 不能分配给类型 '"y"'.

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

推荐答案

如您所见,C 类的 privateprotected 属性不要作为 keyof C 的一部分出现.这通常是可取的行为,因为大多数尝试对具有私有/受保护属性的类进行索引都会导致编译错误.有一个 建议 允许 映射一个类型到一个版本,其中私有/受保护的属性是公开的,这会给你一种方法这样做...但此功能尚未在 TypeScript 3.5 中实现.

As you noticed, private and protected properties of a class C do not appear as part of keyof C. This is usually desirable behavior, since most attempts to index into a class with a private/protected property will cause a compile error. There is a suggestion to allow mapping a type to a version where the private/protected properties are public, which would give you a way to do this... but this feature has not been implemented as of 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,以免对类的外部用户不可见.您可以使用模块/命名空间仅导出您想要的类的方面,如下所示:

But maybe you don't actually need the properties to be private, so much as not visible to outside users of the class. You can use a module/namespace to export only the facets of your class that you want, like this:

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,它省略了 x 属性(和 keys 属性) 来自 _A.所以你得到了你想要的内部行为,而 NotExported.A 的外部行为类似于 Privates.A 的外部行为.xkeys 由于违反 private 而无法访问,而是无法访问,因为它们不是导出的 A 类型.

In NotExported, the class constructor _A and the corresponding type _A are not directly exported. Internally, keyof _A contains both the "x" and "y" keys. What we do export is a constructor A and a corresponding type A that omits the x property (and keys property) from _A. So you get the internal behavior you desire, while the external behavior of NotExported.A is similar to that of Privates.A. Instead of x and keys being inaccessible due to private violation, they are inaccessible because they are not part of the exported A type.

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

I actually prefer the latter method of not exporting implementation details rather than exposing the existence of private properties, since private properties actually have a lot of impact on how the corresponding classes can be used. That is, private is about access control, not about encapsulation.

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

Okay, hope that helps; good luck!

代码链接

这篇关于列出类的私有属性名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆