I have a generic base service for performing CRUD operations where sub classes specify a specific entity (they also specify a respective end point url). The base class declares a protected api url that each sub class then initializes accordingly in the constructor.
Now I came across the need to actually change the signature of one of the operations for a specific entity, namely adding some parameters to get
.
So I followed this to create a type without the get
and than provide a new signature. This works, but now the protected api url property does not exist anymore, which I don't understand.
I created a boiled down example to demonstrate this here.
This is the code (errors in SubClass2
):
interface Type1 {
name: string;
}
interface Type2 {
price: number;
}
class Service1 {}
class BaseClass<T> {
protected prop1: string = 'BaseClass';
constructor(protected dep1: Service1) {}
foo(){
console.log(`${this.prop1}.foo`);
}
bar(){
console.log(`${this.prop1}.bar`);
}
}
class SubClass1 extends BaseClass<Type1> {
constructor(protected dep1: Service1) {
super(dep1);
this.prop1 = 'SubClass1';
}
}
type BaseClassWithoutBar = new <T>(dep1: Service1) => {
[P in Exclude<keyof BaseClass<T>, 'bar'>]: BaseClass<T>[P];
};
const BaseClassWithoutBar: BaseClassWithoutBar = BaseClass;
class SubClass2 extends BaseClassWithoutBar<Type2> {
constructor(protected dep1: Service1) {
super(dep1);
this.prop1 = 'SubClass2'; // <- Error here
}
bar(name: string) {
console.log(`${this.prop1}.bar -> ${name}`); // <- Error here
}
}
const sub1: SubClass1 = new SubClass1(new Service1());
const sub2: SubClass2 = new SubClass2(new Service1());
sub1.foo();
sub1.bar();
sub2.foo();
sub2.bar('Bob');
Of course I can get by this e.g. by making the property public or by creating a new method with a different name, but I would still like to know what is actually happening here.
CodePudding user response:
keyof
operator does not include private and protected properties.