Я предполагаю, что тип выражения this.handlers[type]
вызывает вашу ошибку:
В теле функции addHandler
мы не знаем, какое из двух значений "OnTick"
или "OnKeyDown"
свойство type
имеет, поэтому для доступа к свойству предполагается его базовый тип keyof IHandlerMap
или "OnTick" | "OnKeyDown"
. Доступ к свойству this.handlers[type]
будет преобразован в тип HandlersType[keyof IHandlerMap]
, который равен BasicHandler[] | KeyPressHandler[]
.
Теперь, когда мы вызываем this.handlers[type].push
, метод push
может быть вызван либо с помощью BasicHandler[]
, либо KeyPressHandler[]
, так что его типом является union обоих push
методов:
| (...items: BasicHandler[]): number
| (...items: KeyPressHandler[]): number
Начиная с TS 3.3, вы можете фактически вызывать union тип функций , но их параметры пересекаются (&
). Сигнатура push
выглядит примерно так:
(method) Array<T>.push(items: (BasicHandler & KeyPressHandler)[]): number
BasicHandler
не имеет параметров функции, KeyPressHandler
один. Таким образом, пересечение приводит к ... нет ожидаемых параметров. Вы можете добавить аргумент, например s: string
к BasicHandler
, и он станет более очевидным (наведите курсор на push
затем).
Что мы можем сделать?
Использовать дополнительную переменную для this.handlers
с типом HandlersTypeMixed
или используйте его для this.handlers
напрямую. Примечание: (BasicHandler | KeyPressHandler)[]
!==
BasicHandler[] | KeyPressHandler[]
. Только первое не приведет к объединению типов функций и не позволит push
. Детская площадка
type HandlersTypeMixed = { [key in keyof IHandlerMap]: (BasicHandler | KeyPressHandler)[] }
public addHandler<K extends keyof IHandlerMap>(
type: K,
handler: IHandlerMap[K]
) {
const hs: HandlersTypeMixed = this.handlers
hs[type].push(handler);
}