绑定到全局 JS 值
首先,确保你要绑定的值不在我们提供的 API 中。
一些 JS 值,例如 setTimeout,存在于全局作用域内。你可以像这样绑定到它们:
(我们已经在 Js.Global 模块中提供了 setTimeout、clearTimeout 等绑定。)
上面的代码会绑定到 JavaScript 的 setTimeout 方法,和与之对应的 clearTimeout 方法。external 的类型标注指定 setTimeout 需要满足:
- 接受一个参数为 - unit且返回- unit的函数(它在 JS 端变成一个不接受任何内容且不返回任何内容的函数(指返回- undefined))。
- 和一个调用回调函数的延时值。 
- 返回一个数字,即 timeout 的 ID。这个数字可能会很大,所以我们将其建模为浮点数,而不是 32 位整数。 
技巧和诀窍
以上情况并不理想。想想怎么让 setTimeout 返回的 float 来作为 clearTimeout 的输入。你没办法保证将 setTimeout 的返回值传递给 clearTimeout!据我们所知,有人可能把 Math.random() 传递给后者。
我们正在使用具有出色类型系统的语言!让我们利用一个流行的特性来解决这个问题:抽象类型。
显然,timerId 是一个只能通过 setTimeout 创建的类型!现在我们可以保证 clearTimeout 将 收到一个有效的 ID。timerId 是否是数字只是一个实现细节。
由于 external 是内联的,我们最终得到的 JS 输出与手写 JS 一样可读。
全局模块
如果你想要绑定一个全局模块内的值,例如 Math.random,可以将 scope 附加到被 val 标注的 external:
你可以通过传递一个元组给 scope 来绑定一个任意深度的对象:
这将绑定到 window.location.ancestorOrigins.length。
特殊全局值
像 __filename 和 __DEV__ 这样的全局值可能会不存在;你甚至不能将它们建模为 option,因为仅仅是在 ReScript 中引用它们(然后编译为 JS)就会触发常见的 Uncaught ReferenceError: __filename is not defined 错误,例如在浏览器环境中就会这样。
对于这些麻烦的全局值,ReScript 提供了一种特殊的方法:%external(a_single_identifier)。
第一行的 typeof 检查不会触发 JS ReferenceError。
另一个例子: