Reputation: 96546
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
.
Upvotes: 1
Views: 160
Reputation: 3227
It appears you have to annotate the class as accepting string indexes similarly to how its done in the interface (note no concrete function definition):
interface StringDoers {
[key: string]: (s: string) => void;
}
class MyStringDoers implements StringDoers {
[key: string]: (s: string) => void;
public static print(s: string) {
console.log(s);
}
public static printTwice(s: string) {
console.log(s);
console.log(s);
}
}
Upvotes: 1