受保护属性的通用 getter 和 setter



考虑这个TypeScript类,它通过将实现拆分为超级类和子类来提供类型检查的通用getter和setter:

class ICompetence {
protected _id : number | undefined;
protected name: string | undefined;
}
export default class Competence extends ICompetence {
set<K extends keyof ICompetence>(key: K, value: ICompetence[K]): void {
this[key] = value;
}
get<K extends keyof ICompetence>(key: K) : ICompetence[K] {
return this[key];
}
constructor() {
super();
}
}

该类的使用方式如下:

let competence = new Competence():    
competence.set("name", "name value text");

但是,然后我收到此错误:

error TS2345: Argument of type '"name"' is not assignable to parameter of type

可以通过删除从接口类中保护的注释来克服此错误:

class ICompetence {
_id : number | undefined;
name: string | undefined;
}

TypeScript 是否提供任何功能来避免在保护属性时发生的此类错误?

由于protected仅在设计时生成错误,并且不会阻止运行时的访问,因此您可能会以另一种方式获得类似的行为,方法是从导出的类型中隐藏相关属性,如下所示:

首先,公开父类的属性:

class ICompetence {
_id: number | undefined;
name: string | undefined;
}

然后正常扩展类,但不要导出它,并将其重命名为_Competence("真正的"Competence稍后会到来(

class _Competence extends ICompetence {
otherProperty: string = "hmm"; // demonstrate you can add other things
set<K extends keyof ICompetence>(key: K, value: ICompetence[K]): void {
this[key] = value;
}
get<K extends keyof ICompetence>(key: K): ICompetence[K] {
return this[key];
}
constructor() {
super();
}
}

现在我们准备Competence. 首先,我们定义类型函数Omit,它从类型中删除指定的键:

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>

然后我们导出一个名为Competence的接口和一个名为Competence的值,它们派生自_Competence但不公开来自ICompetence的属性。 当然,它们仍然存在,但类型系统不会公开它们:

export interface Competence extends Omit<_Competence, keyof ICompetence> { }
export const Competence = _Competence as new () => Competence;

现在,在您的消费者代码中,您应该能够执行以下操作:

const competence = new Competence();
competence.name // error at compile time
competence.otherProperty // okay
const name = competence.get("name") // string or undefined

它有效。 希望有帮助。 祝你好运!

我遵循了jcalz回答中的想法,但稍微简化了解决方案:

class ICompetence { ... }
export class Competence extends ICompetence { ... }
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
export interface Competence extends Omit<Competence, keyof ICompetence> { }

然后,该解决方案支持隐藏客户端以访问放置在类 ICompetence 中的属性,而客户端仍然可以访问放置在子类能力中的任何属性。

最新更新