繁体   English   中英

来自泛型类型的查找类型不能分配给“任何”

[英]Lookup type from generic type can't be assigned to “any”

好吧,这个有点难以解释。 我的例子很复杂,但我试图尽可能地简化它,同时保留错误。

type Handler = (...args: any[]) => void;

const handlers: { [eventName: string]: Handler } = {};

type Events = {
  // Map event signature (arg types) to event name
  [eventName: string]: any[];
};

function createOnEvent<UserEvents extends Events>() {
  type ValidEventName = Extract<keyof UserEvents, string>;

  return <EventName extends ValidEventName>(
    eventName: EventName,
    eventHandler: (...args: UserEvents[EventName]) => void,
  ) => {
    handlers[eventName] = eventHandler; // [0] ERROR HERE
  };
}

[0]类型'any []'不能分配给'UserEvents [EventName]'

有两件事令我困惑:

  • UserEvents[EventName]应该等于any[]
  • 我正在尝试将UserEvents[EventName]分配给any[] ,而不是相反...

顺便说一下,这是这个API的使用方式:

type FooEvents = {
  eventOne: [number];
  eventTwo: [string, boolean];
};

const onEvent = createOnEvent<FooEvents>();
onEvent('eventOne', (arg1: number) => null); // OK
onEvent('eventTwo', (arg1: string, arg2: boolean) => null); // OK
onEvent('eventOne', (arg1: string) => null); // error

哪个按预期工作。 失败的唯一部分是当我想将处理handlers存储在处理handlers ,它应该期望具有任何args列表的函数。

我意识到这有点令人困惑,所以如果我能澄清任何事情,请告诉我。 我很高兴能够深究这一点。 谢谢!

原因

您遇到的错误源于这样的事实:当使用--strictFunctionTypes标志时,函数类型在其参数类型中是逆变的

这意味着什么? 这意味着当函数期望其参数具有某种类型时,您可以使用特定参数或比预期类型更宽的参数。

在您的情况下, handlers是通用处理程序的字典。 这些处理程序期望any[]参数。 他们的定义也可以写成:

const handlers: {
  [eventName: string]: (...args: any[]) => void
} = {};

但是,您的eventHandler不仅仅是一个通用的处理程序。 它不接受any[]参数,而是接受UserEvents描述的一些非常具体的参数。 这违背了逆向的观点 - 传递给函数的参数不能比其签名所要求的更具体。 换句话说, typeof eventHandler不能分配给Handler

你可以做什么

  • 通过使用类型断言在本地eventHandler的类型:

     handlers[eventName] = eventHandler as Handler; 
  • 使编译器接受处理程序的特定定义:

     type Handler<T extends any[] = any> = (...args: T) => void; 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM