0

I have this interface:

interface Events {
  SERVER_START: {
    version: string;
  };
  SERVER_READY: {
    host: string;
    port: number;
  };
  SERVER_STOP: undefined;
  SERVER_STOP_ERROR: {
    error: Error;
  };
  SERVER_CONNECTION_INCOMING: {
    clientId: string;
    address: string;
    port: number;
  };
 ...
}

is it possible to map functions parameters like this?

function logEvent(type: keyof Events, data?: Events[keyof Events]): void;

This work almost fine, since I can call logEvent like this:

// this is correct:
logEvent('SERVER_START', { version: '0.1.0' });

// but this is also correct, which shouldn't
logEvent('SERVER_START');
logEvent('SERVER_START', { host, port });

Of course, intellisense also don't work as expected so, I had to manually define all the overloadings of the function like...

function logEvent(type: 'SERVER_START', data: Events['SERVER_START']): void;
function logEvent(type: 'SERVER_READY', data: Events['SERVER_READY']): void;
function logEvent(type: 'SERVER_STOP'): void;
...

which works like a charm, but it looks to me like there should be a better way to define all of this automagically...

Update:

So, the idea is not having only Events but extending that interface with other definitions as well, so the idea would be to have a generic function like

function logEvent<E extends Events>(type: keyof E, data?: E[keyof E]): void;

so you can actually do

interface MoreEvents extends Events {
  FOOBAR: {
    foo: string;
    bar: number;
  };
}

// call it with the original ones
logEvent('SERVER_START', { version: '0.1.0' });

// call it also with the new events
logEvent<MoreEvents>('FOOBAR', { foo, bar });

but with proper type checking

1 Answer 1

1

You can redefine your logEvent function using generics

logEvent<E extends Events>(type: keyof E, data?: E[keyof E]): void;

Update

This solution works with the updated question. Check that playground

Sign up to request clarification or add additional context in comments.

5 Comments

omg so stupid solution... I tried lots of them but didn't get the correct syntax. Thanks this works. By the way, making the second parameter optional works just fine too :)
Happy to help. I was not sure about the second argument
wait, if T extends keyof Events that means that, there could be some values which will Events[T] will be undefined, right? So that's not really valid...
To answer your comment if you have logEvent<T extends keyof Events> then T will always be one of the key of Events, so no undefined
It also works with the updated question, check the playground in the updated answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.