Reputation: 40084
I suppose this has been asked before but I am having trouble phrasing it to find a solutions so apologies in advance.
I have an enum type:
enum Events {
FOO = 'foo',
BAR = 'bar'
}
I have a function that in turn accepts a function. The function it accepts has a type EventHandler
export const wrapEventFn = async (fn: EventHandler): Promise<unknown> => {
...
The type definition for EventHandler
is:
type EventHandler = (event: Events) => Promise<void>
Now the functions that I pass are themselves limited in what events they can handle. For example:
export const actionHandler = async (
event: Events.FOO
): Promise<void> => {...
Doing the above does not work and TS yields error:
wrapEventFn(actionHandler) // actionHandler is underlined w error
Error
Argument of type '(event: Events.FOO) => Promise<void>' is not assignable to parameter of type 'EventHandler'.
Types of parameters 'event' and 'event' are incompatible.
Type 'Events' is not assignable to type
How can I fix this?
Upvotes: 1
Views: 157
Reputation: 45252
Instead of enum
, use String Literal Types
type Events = 'foo' | 'bar'
Now make EventHandler take a generic object that is assignable to type Events
:
type EventHandler<T extends Events> = (event: T) => Promise<void>;
declare function wrapEventFn<T extends Events>(fn: EventHandler<T>): Promise<unknown>;
Now we can create your type which is a known subset of the available events:
type SpecializedEvents = 'foo';
declare function actionHandler(event: SpecializedEvents): Promise<void>;
Now we can call it like so:
wrapEventFn<SpecializedEvents>(actionHandler);
As it turns out, we don't even need to state the generic type, the typescript compiler can infer it. It's much more readable to just write this:
wrapEventFn(actionHandler);
To demonstrate this works, we can attempt to pass an incompatible type in:
type CompletelyTheWrongType = 'this' | 'is' | 'wrong';
declare function wrongActionHandler(event: CompletelyTheWrongType): Promise<void>;
wrapEventFn(wrongActionHandler);
The error this produces reads as follows:
Arguments of type '(event: CompletelyTheWrongType) => Promise' is not assignable to parameter of type 'EventHandler'...
Upvotes: 2