Consider the following code:
interface StringDoers {
[key: string]: (s: string) => void;
}
class MyStringDoers implements StringDoers {
public static print(s: string) {
console.log(s);
}
public static printTwice(s: string) {
console.log(s);
console.log(s);
}
}
This gives me a type error:
Class 'MyStringDoers' incorrectly implements interface 'StringDoers'.
Index signature is missing in type 'MyStringDoers'
But from Javascript's point of view, it does implement StringDoers. In a Javascript console I can do this perfectly well:
class MyStringDoers {
static print(s) {
console.log(s);
}
static printTwice(s) {
console.log(s);
console.log(s);
}
}
MyStringDoers["printTwice"]("hello");
I wondered if it is because [string] can also return undefined, e.g.
MyStringDoers["foo"]; // undefined
However even changing the interface to this does not work:
interface StringDoers {
[key: string]: ((s: string) => void) | undefined;
}
How can I make this work? The constraint is that StringDoers is in a third party library so I cannot change it. And I want an actual type that knows about all of the methods - i.e. not just:
const doers: StringDoers = {
print(s: string) {
console.log(s);
},
...
}
I expect someone who doesn't know the answer will try to make themselves feel better by asking why I'd want to do this, so: my use case is adding proper typing for Vuex's MutationTree.
public static meth(n: number): string { /* */ }and still have a valid class without any compiler warnings. In that case implementing the interface doesn't add any meaning to it. The real answer is in the question I linked to: you can't implement indexable types in a class the way you want to.[key: string]. What's the difference betweenMyStringDoers['foo']andmap['foo']? Nothing in terms of the types as far as I can tell.