我有这个界面:
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 });
但具有正确的类型检查
答案 0 :(得分:1)
您可以使用泛型重新定义logEvent
函数
logEvent<E extends Events>(type: keyof E, data?: E[keyof E]): void;
更新
此解决方案适用于更新的问题。选中that playground