列出类的私有属性名称 [英] List private property names of the class
问题描述
我需要使用类属性名称的一些子集作为映射中的值以在类内部使用.在以下示例中,我已将 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
类的 private
和 protected
属性不要作为 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
的外部行为.x
和 keys
由于违反 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屋!