Typescript 类型脚本映射接口

Typescript 类型脚本映射接口,typescript,Typescript,我有这个界面: interface Events { SERVER_START: { version: string; }; SERVER_READY: { host: string; port: number; }; SERVER_STOP: undefined; SERVER_STOP_ERROR: { error: Error; }; SERVER_CONNECTION_INCOMING: { clientId: st

我有这个界面:

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;
  };
 ...
}
可以这样映射函数参数吗

function logEvent(type: keyof Events, data?: Events[keyof Events]): void;
这项工作几乎很好,因为我可以这样调用logEvent:

// 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 });
当然,intellisense也不能像预期的那样工作,所以,我必须手动定义函数的所有重载,如

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;
...
这就像一个魅力,但在我看来,应该有一个更好的方式来定义所有这些自动

更新:

因此,我们的想法不仅仅是拥有事件,而是通过其他定义扩展该接口,因此我们的想法是拥有一个通用函数,如

function logEvent<E extends Events>(type: keyof E, data?: E[keyof E]): void;
所以你可以做到

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 });
但是通过适当的类型检查,您可以使用泛型重新定义logEvent函数

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


此解决方案适用于更新的问题。检查

omg如此愚蠢的解决方案。。。我尝试了很多,但没有得到正确的语法。谢谢,这很有效。顺便说一下,将第二个参数设置为可选也很好:乐意帮忙。我不确定第二个参数,等等,如果T扩展了事件的范围,这意味着,可能有一些值,这些值将是未定义的,对吗?所以这不是真的有效…要回答您的评论,如果您有logEvent,那么T将始终是事件的关键之一,因此没有undefinedIt也适用于更新的问题,请检查更新答案中的游乐场