Тип конфликтов с прослушивателями событий

Я пытаюсь присоединить обработчик событий к узлу 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")))
Другие вопросы по тегам