Error: This expression has type Dom_html.divElement Js.t but an expression was expected of type < get : int -> 'a Js.meth; terminal : 'b -> 'c -> unit Js.meth > Js.t

Context: I am trying to get this example to work.

  1. I run into an runtime error of not having jQuery due to virtual_dom/terminal.ml at master · janestreet/virtual_dom · GitHub
Js.Unsafe.global##jQuery (Js.string "<div width='400px' height='300px'>")
  1. One solution to this is to bundle jQuery, but, since jQuery is only used once ,I’d prefer to rip out the dependency, so I replace

old_code

      let div : < terminal : _ -> _ -> unit Js.meth ; get : int -> _ Js.meth > Js.t =
        Js.Unsafe.global##jQuery (Js.string "<div width='400px' height='300px'>")
      in

my replacement code

let create_div () =
  let div = Dom_html.(createDiv document) in
  div##.style##.width := Js.string "400px";
  div##.style##.height := Js.string "300px";
  div

...

      let div : < terminal : _ -> _ -> unit Js.meth ; get : int -> _ Js.meth > Js.t =
        create_div ()
        (* Js.Unsafe.global##jQuery (Js.string "<div width='400px' height='300px'>") *)
      in
  1. This generates an error of

error

55 |         create_div ()
             ^^^^^^^^^^^^^
Error: This expression has type Dom_html.divElement Js.t
       but an expression was expected of type
         < get : int -> 'a Js.meth; terminal : 'b -> 'c -> unit Js.meth >
         Js.t

  1. This error makes total sense; we create_div () has type Dom_html.divElement Js.t , but we need an object of type < ... long signature ... >

question

How do we fix this ?

1 Like

I’m afraid it’s a bit trickier than that. If we look at what < ... long signature ... > actually means, it’s the object signature for an object. In particular, it has 2 methods:

  • get : int -> 'a Js.meth is the standard jQuery collection.get(). It returns the Dom_html.divElement Js.t created. This is kind of what you’ve replicated in your code.
  • terminal : _ -> _ -> unit Js.meth comes from the jQuery terminal plugin

You can’t remove the jQuery dependency as configured in example.html because the terminal itself comes from jQuery Terminal. All the other code is:

  • defining an interpreter for the terminal in this example. Here, we just have setting/getting values for keys
  • implementing the autocomplete API, either for the “set”/“get” commands, or for some existing key of “get”
  • other configuration
  • Providing all this config to the jQuery terminal “create” API, and putting that in a Vdom,Node.widget, which seems to tell virtual_dom that the children and state of some vdom element are going to be explicitly managed by the dev. In this case, by jQuery terminal.
  • Nesting that widget into some other vdom HTML
  • On boot, mounting all this into the example HTML page

Hope this helps!

1 Like

Not sure if this went in to your wanting to pull out the jquery dependency or not, but for what it’s worth, the size of including jquery will be dwarfed by the size of the jsoo code. (~600kb jsoo and ~90kb jquery.)

This is the core of my misunderstanding. I did not realize there was a jQuery Terminal lib, thought OCaml was using jQuery only for creating a div. I was looking forward to seeing the “minimal terminal” virtual-dom managed to define. LOL.

I’m already at ~5-10 MB for jsoo output size. :slight_smile:

The goal was to minimize external dependencies for (1) easier to understand and (2) whenever I come back to npm dependencies in 6-12 months, something tends to break.

1 Like

Just in case you didn’t realize…when you compile with --profile=release you get much smaller jsoo output.

I just tested:

(dune build; esbuild minify) / (dune build --profile=release; esbuild minify) = ~3

I was not expecting such huge reductions (since esbuild was already doing minify / bundling).

Yeah, it is because jsoo with dune dev profile isn’t doing the dead code elimination. (See here and here.)

1 Like