我正在尝试实现suggestion here,特别是此功能:
function eventAssigner<Handlers extends Record<keyof Handlers, (e: any) => any>,
Discriminant extends keyof any>(
handlers: Handlers,
discriminant: Discriminant
) {
return <Key extends keyof Handlers>(
event: Record<Discriminant, Key> & (Parameters<Handlers[Key]>[0])
): ReturnType<Handlers[Key]> => handlers[event[discriminant]](event);
}
但是,eventAssigner
拒绝了我提供的事件的类型,尽管在我看来类型是匹配的。您能指出类型的不同之处吗?
Here's a playground。请在proxyEventAssigner
函数中找到错误。
以下是代码的其余部分,以防万一:
// this is the command comming from outside
type UnauthenticatedCommand<CmdName extends keyof CommandMap> =
CommandMap[CmdName]
& { cmdName: CmdName }
& { jwtToken: string }
// this is the authenticated version of the same command
type AuthenticatedCommand<CmdName extends keyof CommandMap> =
CommandMap[CmdName]
& { authenticatedUser: { id: string } }
& { cmdName: CmdName }
interface CommandMap {
event1: { attr1: string; attr2: number };
event2: { attr3: boolean; attr4: string };
}
const handlers: {
[CmdName in keyof CommandMap]: (e: AuthenticatedCommand<CmdName>) => Promise<void>
} = {
event1: ({attr1, attr2}) => Promise.resolve(),
event2: ({attr3, attr4}) => Promise.resolve(),
};
//-------------------------------------------------
//this function is here just for a bit of context as to
// why the eventAssigner is receiving AuthenticatedCommand<CmdName>
const topHandler =
<CmdName extends keyof CommandMap>(e: UnauthenticatedCommand<CmdName>): Promise<void> =>
proxyEventAssigner(authenticateUser(e));
const proxyEventAssigner =
<CmdName extends keyof CommandMap>(e: AuthenticatedCommand<CmdName>): Promise<void> =>
eventAssigner(handlers, 'cmdName')(e);
const authenticateUser =
<CmdName extends keyof CommandMap>(e: UnauthenticatedCommand<CmdName>): AuthenticatedCommand<CmdName> => {
throw new Error('unimplemented');
};
//-------------------------------------------------------
function eventAssigner<Handlers extends Record<keyof Handlers, (e: any) => any>,
Discriminant extends keyof any>(
handlers: Handlers,
discriminant: Discriminant
) {
return <Key extends keyof Handlers>(
event: Record<Discriminant, Key> & (Parameters<Handlers[Key]>[0])
): ReturnType<Handlers[Key]> => handlers[event[discriminant]](event);
}