考虑这个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是否提供任何功能以避免在属性受到保护时发生此类错误?
答案 0 :(得分:0)
由于protected
仅在设计时生成错误并且不会阻止在运行时访问,因此您可能会通过隐藏导出类型的相关属性来获得类似的行为,例如这样:
首先,将父类的属性设为public:
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
它有效。希望有所帮助。祝你好运!
答案 1 :(得分:0)
我在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中的属性,而客户端仍然可以访问子类Competence中的任何属性。