为什么此参数类型不能分配给期望的参数?

时间:2019-09-13 14:32:47

标签: typescript types casting type-conversion

我正在尝试实现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);
}


0 个答案:

没有答案