我正在尝试使用Fable将事件处理程序附加到DOM节点:
let handleIntroSubmit (event: Event) = ()
container
.querySelector("#some-node")
.addEventListener("click", handleIntroSubmit)
然而,这失败并出现以下错误:
这个错误令我感到困惑,因为:
查看Fable.Import.Browser的来源,我发现EventListenerOrEventListenerObject
defined:
EventListenerOrEventListenerObject =
U2<EventListener, EventListenerObject>
EventListener
defined就是这样:
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
泛型类型来自哪里,尽管我已经为函数handleIntroSubmit
参数提供了一个explict类型的注释。 / p>
我理想地想知道为什么上面的内容不起作用,这里的错误意味着什么,以及使用Fable添加事件监听器的最佳/类型安全(没有unbox)方式。
答案 0 :(得分:1)
这里有两个不同的问题。
首先,您链接only appeared in master
two days ago的EventListener
定义。在此之前,定义是Func<Event, unit>
,它是一个.NET委托,与F#function Event -> unit
完全不同。从错误消息中可以看出,您使用的是早期版本的库。
要解决此问题,请重新定义您的功能:
let handleIntroSubmit = Func<Event, unit>( fun e -> () )
这将为其提供Func<Event, unit>
的类型,这是EventListener
(当前)的内容。
其次,即使handleIntroSubmit
与EventListener
兼容,也不意味着它也会与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")))