TypeScript Generics

Hey. I need some help with TypeScript generics
9 Replies
domi?
domi?2y ago
So this is what my sourcecode looks like:
type ListenerType = 'on' | 'once' | 'handle' | 'handleOnce';

type ListenerCallback<Path extends ListenerType> = Electron.IpcMain[Path];

type Listener<EventName extends ListenerType> = {
event: EventName;
callback: ListenerCallback<EventName>;
};

type ListenerArray = Listener[];

const a: ListenerArray = [
{

}
];
type ListenerType = 'on' | 'once' | 'handle' | 'handleOnce';

type ListenerCallback<Path extends ListenerType> = Electron.IpcMain[Path];

type Listener<EventName extends ListenerType> = {
event: EventName;
callback: ListenerCallback<EventName>;
};

type ListenerArray = Listener[];

const a: ListenerArray = [
{

}
];
So I have ListenerType, which can be one of the 4 values listed above. And ListenerCallback, which will return a specific type based on which ListenerType was specified. So let's say ListenerCallback<'on'> would return number while ListenerCallback<'handle'> would return string And I'd like to have an array objects, where you specify an event with the event key, and the callback needs to be of type of that event. So let's say my event is on, then I'd like the type of the callback to be ListenerCallback<'on'> But I get this error with this current setup: Generic type 'Listener' requires 1 type argument(s) Which makes sense, but how else can I infer the types this way?
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
domi?
domi?2y ago
Let me try your example The issue with this is, that ListenerCallback should depend on the "event" key in the object. The callback function should have a different return type when the event is "on" compared to when the event is "handle" In your implementation, ListenerCallback was just a union type of all the possibilities that it could be
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
domi?
domi?2y ago
I managed to get a working version, I just don't really understand why the extends unknown is needed. Without it, it doesn't work.
type ListenerType = 'on' | 'once' | 'handle' | 'handleOnce';

type ListenerCallback<Type extends ListenerType> = Parameters<Electron.IpcMain[Type]>['1'];

type Listener<Event extends ListenerType> = (
Event extends unknown
? {
event: Event;
callback: ListenerCallback<Event>;
}
: never
);

type ListenerArray = Listener<ListenerType>[];

const a: ListenerArray = [];
type ListenerType = 'on' | 'once' | 'handle' | 'handleOnce';

type ListenerCallback<Type extends ListenerType> = Parameters<Electron.IpcMain[Type]>['1'];

type Listener<Event extends ListenerType> = (
Event extends unknown
? {
event: Event;
callback: ListenerCallback<Event>;
}
: never
);

type ListenerArray = Listener<ListenerType>[];

const a: ListenerArray = [];
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
domi?
domi?2y ago
Without it, callback becomes any in the a array
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
domi?
domi?2y ago
wow this is quite useful thanks man
Want results from more Discord servers?
Add your server