Some block code is not dead code, but disappeared in the output compiled js

The yellow block in the picture above is disappeared is the compiled js, is that a bug?

This is the example code playground. It looks like when your function contains optional labeled arguments, and if the output of this function is unused, then the function will be judged to dead code by rescript compiler.

When using optional labelled arguments you must include a () argument at the end.

Note for the sake of the type system, whenever you have an optional argument, you need to ensure that there’s also at least one positional argument (aka non-labeled, non-optional argument) after it. If there’s none, provide a dummy unit (aka () ) argument.

Otherwise the compile doesn’t know when to curry the function or invoke it.

In your playground you need to change:

let bindDrag = (element: Dom.element, ~onDragStart: option<unit => unit>=?) => {


let bindDrag = (element: Dom.element, ~onDragStart: option<unit => unit>=?, ()) => {

And let _ = box->bindDrag to let _ = box->bindDrag()


Thanks, it’s my negligence, but may be the rescript compiler should make a warning about this case i think.

Yeah this is easy to get tripped up by. One neat trick if you’re indeed expecting a unit, like you are now, is to do let () = box->bindDrag instead of assigning to _. That’ll make the compiler complain about your call not returning unit, and force you to apply it properly.

You can also annotate _ as what you expect to return, like let _: Disposable.t = somethingThatShouldReturnADisposable().

I believe there’s also ongoing work in exploring making currying opt in rather than opt out, which would alleviate most of situations like this.


You can also pipe to ignore instead of assigning to _ eg. box->bindDrag->ignore which will surface a warning.

1 Like