Per my understanding of https://www.typescriptlang.org/docs/handbook/2/classes.html#this-types I should be able to use this
as a type in place of the name of the base class to allow inheriting classes to sub in their class type.
I am trying to use this to create a method that takes an object which has the same properties as the class it belongs to, and uses them to create a modified copy:
type ClassProperties<C> = {
[K in keyof C as C[K] extends Function ? never : K]: C[K]
}
abstract class BaseClass {
clone() { return structuredClone(this); }
toModified(change: Partial<ClassProperties<this>>) {
const c = this.clone();
type changetype = typeof change;
type changekeys = keyof changetype;
type changevals = changetype[changekeys];
Object.entries(change).forEach(([k, v]: [changekeys, changevals]) => { (c[k] as changevals) = v; });
return c;
}
}
export class ConcreteClass extends BaseClass {
constructor(public a: number, public b: string = "", public c: boolean = false) {
super();
}
}
This gives the following error:
typescript [2345]: Argument of type '([k, v]: [keyof ClassProperties<this>, changevals]) => void' is not assignable to parameter of type '(value: [string, unknown], index: number, array: [string, unknown][]) => void'.
If I write out an impl for the inheriting class, it works:
export class ConcreteClass extends BaseClass {
constructor(public a: number, public b: string = "", public c: boolean = false) {
super();
}
toModified(change: Partial<ClassProperties<ConcreteClass>>) {
const c = this.clone();
type changetype = typeof change;
type changekeys = keyof changetype;
type changevals = changetype[changekeys];
Object.entries(change).forEach(([k, v]: [changekeys, changevals]) => { (c[k] as changevals) = v; });
return c;
}
}
But since I have several classes that inherit from the base class, I'd really like to avoid the duplication.