打字稿映射的接口

时间:2019-10-14 11:52:12

标签: 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: 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 });

当然,智能感知也无法按预期工作,因此,我不得不手动定义函数的所有重载,如...

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;
...

这就像一个咒语,但在我看来应该有一种更好的方法来自动定义所有这些内容...

更新

因此,该想法不仅具有Events,而且还将该接口与其他定义一起扩展,因此该想法将是具有类似的通用功能

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 });

但具有正确的类型检查

1 个答案:

答案 0 :(得分:1)

您可以使用泛型重新定义logEvent函数

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

更新

此解决方案适用于更新的问题。选中that playground