我需要在映射中使用类属性名称的某些子集作为值,以便在类内使用。在下面的示例中,我用数组替换了映射。问题是,如果属性被标记为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’。
发布于 2019-07-17 14:32:56
正如您注意到的,类private和protected属性C不显示为keyof C的一部分。这通常是可取的行为,因为大多数尝试索引到具有私有/受保护属性的类中都会导致编译错误。有一个建议允许映射类型到一个私有/受保护的属性是公共的版本,这将为您提供一种方法.但是这个特性在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的行为相似。x和keys不是由于private冲突而无法访问的,而是因为它们不是导出的A类型的一部分而无法访问。
实际上,我更喜欢不导出实现细节的后一种方法,而不是公开private属性的存在,因为private属性实际上对如何使用相应的类有很大影响。也就是说,private是关于访问控制,而不是关于封装。
好吧,希望这能帮上忙,祝你好运!
链接到代码
https://stackoverflow.com/questions/57066049
复制相似问题