Last active
December 19, 2022 16:53
-
-
Save jbhoot/db87533e7741b756d48dc2b5bed91a33 to your computer and use it in GitHub Desktop.
Experiments with typing event handlers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@val external document: Dom.document = "document" | |
@val external window: Dom.window = "window" | |
type opts = {useCapture: bool} | |
type ev<'t, 'ct> = { | |
target: 't, | |
currentTarget: 'ct, | |
} | |
module FileReader = { | |
type t | |
@new external make: unit => t = "FileReader" | |
} | |
module AbortSignal = { | |
type t | |
@new external make: unit => t = "AbortSignal" | |
} | |
module Approach1 = { | |
@send | |
external listen_to_click: ( | |
'ct, | |
@as("click") _, | |
ev<'t, 'ct> => unit, | |
option<opts>, | |
) => unit = "addEventListener" | |
@send | |
external listen_to_dblclick: ( | |
'ct, | |
@as("dblclick") _, | |
ev<'t, 'ct> => unit, | |
option<opts>, | |
) => unit = "addEventListener" | |
let eg1 = listen_to_click( | |
document, | |
(event: ev<Dom.element, Dom.document>) => { | |
let tgt = event.target | |
let ctgt = event.currentTarget | |
}, | |
None, | |
) | |
let eg2 = listen_to_dblclick( | |
window, | |
(event: ev<Dom.element, Dom.window>) => { | |
let tgt = event.target | |
let ctgt = event.currentTarget | |
}, | |
None, | |
) | |
} | |
module Approach2 = { | |
@send | |
external listen: ( | |
'ct, | |
@string | |
[ | |
| #click(ev<'t, 'ct> => unit) | |
| #dblclick(ev<'t, 'ct> => unit) | |
| #abort(ev<FileReader.t, FileReader.t> => unit) | |
| @as("abort") #abort2(ev<AbortSignal.t, AbortSignal.t> => unit) | |
], | |
option<opts>, | |
) => unit = "addEventListener" | |
let eg1 = listen( | |
document, | |
#click( | |
(event: ev<Dom.element, Dom.document>) => { | |
let tgt = event.target | |
let ctgt = event.currentTarget | |
}, | |
), | |
None, | |
) | |
let eg2 = listen( | |
window, | |
#dblclick( | |
(event: ev<Dom.element, Dom.window>) => { | |
let tgt = event.target | |
let ctgt = event.currentTarget | |
}, | |
), | |
None, | |
) | |
let eg3 = listen( | |
AbortSignal.make(), | |
#abort2( | |
event => { | |
let tgt = event.target | |
let ctgt = event.currentTarget | |
}, | |
), | |
None, | |
) | |
} | |
module Approach3 = { | |
type name = [#click | #dblclick] | |
@send | |
external listen_to_mouse_ev: ( | |
'ct, | |
name, | |
ev<'t, 'ct> => unit, | |
option<opts>, | |
) => unit = "addEventListener" | |
let eg1 = listen_to_mouse_ev( | |
document, | |
#click, | |
(event: ev<Dom.element, Dom.document>) => { | |
let tgt = event.target | |
let ctgt = event.currentTarget | |
}, | |
None, | |
) | |
let eg2 = listen_to_mouse_ev( | |
document, | |
#dblclick, | |
(event: ev<Dom.element, Dom.document>) => { | |
let tgt = event.target | |
let ctgt = event.currentTarget | |
}, | |
None, | |
) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
external document : Dom.document = "document" [@@val] | |
external window : Dom.window = "window" [@@val] | |
module FileReader = struct | |
type t | |
external make : unit -> t = "FileReader" [@@bs.new] | |
end | |
module AbortSignal = struct | |
type t | |
external make : unit -> t = "AbortSignal" [@@bs.new] | |
end | |
type opts = { useCapture : bool } | |
type ('t, 'ct) ev = | |
{ target : 't | |
; currentTarget : 'ct | |
} | |
module Approach1 = struct | |
external listen_to_click : | |
'ct -> (_[@as "click"]) -> (('t, 'ct) ev -> unit) -> opts option -> unit | |
= "addEventListener" | |
[@@send] | |
external listen_to_dblclick : | |
'ct -> (_[@as "dblclick"]) -> (('t, 'ct) ev -> unit) -> opts option -> unit | |
= "addEventListener" | |
[@@send] | |
let eg1 = | |
listen_to_click document | |
(fun (event : (Dom.element, Dom.document) ev) -> | |
let tgt = event.target in | |
let ctgt = event.currentTarget in | |
()) | |
None | |
let eg2 = | |
listen_to_dblclick window | |
(fun (event : (Dom.element, Dom.window) ev) -> | |
let tgt = event.target in | |
let ctgt = event.currentTarget in | |
()) | |
None | |
end | |
module Approach2 = struct | |
(* NOTE: The polymorphic variant MUST BE "inlined". The following code does | |
not work. *) | |
(* type ('t, 'ct) name = *) | |
(* ([ `click of ('t, 'ct) ev -> unit *) | |
(* | `dblclick of ('t, 'ct) ev -> unit *) | |
(* ] *) | |
(* [@string]) *) | |
(* external listen : 'ct -> ('t, 'ct) name -> opts option -> unit *) | |
(* = "addEventListener" *) | |
(* [@@send] *) | |
(* It compiles to: *) | |
(* document.addEventListener({ *) | |
(* NAME: "click", *) | |
(* VAL: (function ($$event) { *) | |
(* }) *) | |
(* }, undefined); *) | |
external listen : | |
'ct | |
-> ([ `click of ('t, 'ct) ev -> unit | |
| `dblclick of ('t, 'ct) ev -> unit | |
| `abort_abortsignal of (AbortSignal.t, AbortSignal.t) ev -> unit | |
[@as "abort"] | |
| `abort_filereader of (FileReader.t, FileReader.t) ev -> unit | |
[@as "abort"] | |
] | |
[@string]) | |
-> opts option | |
-> unit = "addEventListener" | |
[@@send] | |
let eg1 = | |
listen document | |
(`click | |
(fun (event : (Dom.element, Dom.document) ev) -> | |
let tgt = event.target in | |
let ctgt = event.currentTarget in | |
())) | |
None | |
let eg2 = | |
listen window | |
(`dblclick | |
(fun (event : (Dom.element, Dom.window) ev) -> | |
let tgt = event.target in | |
let ctgt = event.currentTarget in | |
())) | |
None | |
let eg3 = | |
listen (AbortSignal.make ()) | |
(`abort_abortsignal | |
(fun event -> | |
let tgt = event.target in | |
let ctgt = event.currentTarget in | |
())) | |
None | |
end | |
module Approach3 = struct | |
type name = | |
[ `click | |
| `dblclick | |
] | |
external listen_to_mouse_ev : | |
'ct -> name -> (('t, 'ct) ev -> unit) -> opts option -> unit | |
= "addEventListener" | |
[@@send] | |
let eg1 = | |
listen_to_mouse_ev document `click | |
(fun (event : (Dom.element, Dom.document) ev) -> | |
let tgt = event.target in | |
let ctgt = event.currentTarget in | |
()) | |
None | |
let eg2 = | |
listen_to_mouse_ev document `dblclick | |
(fun (event : (Dom.element, Dom.document) ev) -> | |
let tgt = event.target in | |
let ctgt = event.currentTarget in | |
()) | |
None | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment