I have a Typescript class with 4 different properties, like this:
class MyClass {
private x: number;
private y: number;
private z: number;
private w: number;
}
I want to create four functions that increment these properties:
incrementX() { this.x++; }
incrementY() { this.y++; )
...
However, I don't want the increment logic (++
) to be duplicated, I want to place it in one function. If Typescript had ref parameters like C#, I would do something like:
incrementX() { this.increment(ref this.x); }
increment(p: ref number) { p++; }
Typescript does not support passing by reference. The non type-safe way of implementing this is:
incrementX() { this.increment("x"); }
increment(p: string) {
const self = this as any;
self[p]++;
}
It's not type-safe. I can easily call increment('not-a-property')
without getting an error from the compiler. I've added a runtime check to make sure self[p] is indeed a number, but I still want something the compiler can catch.
Is there a type-safe way of implementing this?
Note: obviously my actual code doesn't increment numbers, but rather does something quite elaborate - not on numbers but on another class type.
You could use keyof
and number extends
maybe? To allow passing only keys of the class which are numbers.
class MyClass {
public a: number = 0;
public b: number = 0;
public c: string = "";
public increment(
key: {
[K in keyof MyClass]-?: number extends MyClass[K] ? K : never
}[keyof MyClass]
) {
this[key]++;
}
}
const test = new MyClass();
test.increment("a");
test.increment("b");
test.increment("c"); // fail
test.increment("d"); // fail