Reputation: 53
In one of my ts modules, I have an interface defined, with a class that implements it like so (cleaned for brevity):
export interface Encoder {
name: string;
exec: (str: string, origParam?: string | null) => string;
}
class NOPEncoder implements Encoder {
public name: "None";
public exec(str: string, origParam?: string | null): string {
// origParam is not important in this case, this method is designed as a no-op
return str;
}
}
However, trying to create a Map<string, Encoder>
is giving me some problems. I've tried both of these methods of constructing a value of said type:
// Method 1
const encoders = new Map<string, Encoder>();
encoders.set("NOP", NOPEncoder);
// Method 2
const encoders = new Map<string, Encoder> ([
["NOP", <Encoder>NOPEncoder],
]);
Both method 1 and method 2 give me an error like "Type 'typeof NOPEncoder' cannot be converted to type 'Encoder'. Property 'exec' is missing in type 'typeof NOPEncoder'."
However, the NOPEncoder
class explicitly implements the Encoder
interface (and the compiler is fine with this), and it clearly has an exec
method. What am I doing wrong here such that the compiler doesn't accept that NOPEncoder
is coercible into an Encoder
instance?
Upvotes: 2
Views: 2109
Reputation: 5337
NOPEncoder
is a class. You are defining the Map
as taking an instance of Encoder
; i.e. the class NOPEncoder
is not an instance of Encoder
, it is a type that extends Encoder
. This should work:
const encoders = new Map<string, Encoder>();
encoders.set("NOP", NOPEncoder());
If you want to store the actual class reference, I am not currently aware of a way to do this in TypeScript. I would be very interested to learn of a way to do this, if anyone knows!
Edited to add: @jcalz has a close-enough method of storing the signature of the type constructor, as Map<string, new (...args: any[]) => Encoder>
. Neat trick, I'll have to play around with it sometime!
Upvotes: 1