Тип конфликтов с прослушивателями событий
Я пытаюсь присоединить обработчик событий к узлу DOM с помощью Fable:
let handleIntroSubmit (event: Event) = ()
container
.querySelector("#some-node")
.addEventListener("click", handleIntroSubmit)
Однако это терпит неудачу со следующей ошибкой:
Эта ошибка сбивает меня с толку, потому что:
Глядя на источник Fable.Import.Browser я нахожу EventListenerOrEventListenerObject
определяется как таковой:
EventListenerOrEventListenerObject =
U2<EventListener, EventListenerObject>
А также EventListener
определяется как таковой:
EventListener = (Event -> unit)
Глядя на это определение, я бы предположил, что handleIntroSubmit
будет совместим с EventListener
и, следовательно, с типом объединения EventListenerOrEventListenerObject
?
Однако, к моему удивлению, я обнаружил, что это на самом деле не совместимо с EventListener
хотя их подписи кажутся мне идентичными. Когда я попробую следующее:
let listener: EventListener = handleIntroSubmit
Я получаю следующую ошибку:
This expression was expected to have type
'EventListener'
but here has type
''a -> unit'
Эта ошибка не имеет смысла для меня, в частности, я понятия не имею, где 'a
универсальный тип происходит из-за того, что я предоставил аннотацию типа explict для функции handleIntroSubmit
аргумент.
В идеале я хотел бы знать, почему вышеупомянутое не работает, что означает ошибка здесь и каков наилучший / типизированный (без распаковки) способ добавления прослушивателя событий с использованием Fable.
2 ответа
У вас есть две отдельные проблемы здесь.
Во-первых, определение EventListener
только что появившиеся ссылки появились в master
два дня назад До этого определение было Func<Event, unit>
, который является делегатом.NET, и совсем не то же самое, что F# функция Event -> unit
, Из сообщения об ошибке видно, что вы используете более раннюю версию библиотеки.
Чтобы это исправить, переопределите вашу функцию следующим образом:
let handleIntroSubmit = Func<Event, unit>( fun e -> () )
Это даст ему тип Func<Event, unit>
, который является то, что EventListener
Сейчас).
Во-вторых, даже если handleIntroSubmit
совместим с EventListener
, это не значит, что он также будет совместим с U2<EventListener, _>
, Это совсем другой тип, почему он будет совместимым?
Чтобы произвести значение U2<EventListener, _>
от значения EventListener
используйте первый конструктор U2
союз - Case1
:
let listener: U2<EventListener, EventListenerObject> = Case1 handleIntroSubmit
Конечно, написание Case1
каждый раз немного утомительно К счастью, для работы с такими случаями базовая библиотека Fable предоставляет удобный оператор !^
:
let listener: U2<EventListener, EventListenerObject> = !^handleIntroSubmit
Актуальная дискуссия о Гитлере Fable.
Это было решено в решении, предоставленном Максимом Мангелем - соответствующая скрипка.
btn.addEventListener("click", !^(Func<_,_>(fun _ -> console.log "clicked2")))