Imagine writing a let binding, but with its body omitted and its type mandatorily written down:
external myCFunction : int => string = "theCFunction";
[@bs.val] external getElementsByClassName : string => array(Dom.element) = "document.getElementsByClassName";
externals can only be at the top level, or inside a module definition. You can't declare them in e.g. a function body.
You'd use an external value/function as if it was a normal let binding.
Tips & Tricks
externals before you get to write 100% pure idiomatic Reason code.
Reason takes interoperating with existing code very seriously. Our type system has very strong guarantees. However, such strong feature also means that, without a great interop system, it'd be very hard to gradually convert a codebase over to Reason. Fortunately, the FFI allows us to cooperate very well with dirty, existing code. The combination of a sound type system + great interop means that we get the benefits of a traditional gradual type system regarding incremental codebase coverage & conversion, without the downside of such gradual type system: complex features to support existing patterns, slow analysis, diminishing return in terms of type coverage, etc.