键入与事件侦听器的冲突

时间:2018-01-22 17:26:05

标签: f# fable-f#

我正在尝试使用Fable将事件处理程序附加到DOM节点:

let handleIntroSubmit (event: Event) = ()

container
    .querySelector("#some-node")
    .addEventListener("click", handleIntroSubmit)

然而,这失败并出现以下错误:

enter image description here

这个错误令我感到困惑,因为:

查看Fable.Import.Browser的来源,我发现EventListenerOrEventListenerObject defined

EventListenerOrEventListenerObject =
    U2<EventListener, EventListenerObject>

EventListener defined就是这样:

EventListener = (Event -> unit)

看看这个定义,我会假设handleIntroSubmitEventListener兼容,因此与联合类型EventListenerOrEventListenerObject兼容?

然而,令我惊讶的是,我发现它实际上并不与EventListener兼容,即使它们的签名看起来与我相同。当我尝试以下内容时:

let listener: EventListener = handleIntroSubmit

我收到以下错误:

This expression was expected to have type
    'EventListener'    
but here has type
    ''a -> unit'

这个错误对我来说毫无意义,特别是我不知道'a泛型类型来自哪里,尽管我已经为函数handleIntroSubmit参数提供了一个explict类型的注释。 / p>

我理想地想知道为什么上面的内容不起作用,这里的错误意味着什么,以及使用Fable添加事件监听器的最佳/类型安全(没有unbox)方式。

2 个答案:

答案 0 :(得分:1)

这里有两个不同的问题。

首先,您链接only appeared in master two days agoEventListener定义。在此之前,定义是Func<Event, unit>,它是一个.NET委托,与F#function Event -> unit完全不同。从错误消息中可以看出,您使用的是早期版本的库。

要解决此问题,请重新定义您的功能:

let handleIntroSubmit = Func<Event, unit>( fun e -> () )

这将为其提供Func<Event, unit>的类型,这是EventListener(当前)的内容。

其次,即使handleIntroSubmitEventListener兼容,也不意味着它也会与U2<EventListener, _>兼容。这是一个完全不同的类型,为什么它会兼容?

要从U2<EventListener, _>的值生成EventListener的值,请使用first constructor of the U2 union - Case1

let listener: U2<EventListener, EventListenerObject> = Case1 handleIntroSubmit

当然,每次写Case1都有点单调乏味。值得庆幸的是,为了处理这类案件,Fable的核心库提供了a handy operator !^

let listener: U2<EventListener, EventListenerObject> = !^handleIntroSubmit

答案 1 :(得分:0)

关于寓言的幽灵的相关discussion

在Maxime Mangel提供的solution中解决了问题 - relevant fiddle

btn.addEventListener("click", !^(Func<_,_>(fun _ -> console.log "clicked2")))