---
title: "Bind to Global JS Values"
description: "JS interop with global JS values in ReScript"
canonical: "/docs/manual/v11.0.0/bind-to-global-js-values"
---
# Bind to Global JS Values
**First**, make sure the value you'd like to model doesn't already exist in our [provided API](api/core).
Some JS values, like `setTimeout`, live in the global scope. You can bind to them like so:
```res example
@val external setTimeout: (unit => unit, int) => float = "setTimeout"
@val external clearTimeout: float => unit = "clearTimeout"
```
```js
// Empty output
```
(We already provide `setTimeout`, `clearTimeout` and others in the [Core API](api/core) module).
This binds to the JavaScript [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrworkerGlobalScope/setTimeout) methods and the corresponding `clearTimeout`. The `external`'s type annotation specifies that `setTimeout`:
- Takes a function that accepts `unit` and returns `unit` (which on the JS side turns into a function that accepts nothing and returns nothing aka `undefined`),
- and an integer that specifies the duration before calling said function,
- returns a number that is the timeout's ID. This number might be big, so we're modeling it as a float rather than the 32-bit int.
### Tips & Tricks
**The above isn't ideal**. See how `setTimeout` returns a `float` and `clearTimeout` accepts one. There's no guarantee that you're passing the float created by `setTimeout` into `clearTimeout`! For all we know, someone might pass it `Math.random()` into the latter.
We're in a language with a great type system now! Let's leverage a popular feature to solve this problem: abstract types.
```res example
type timerId
@val external setTimeout: (unit => unit, int) => timerId = "setTimeout"
@val external clearTimeout: timerId => unit = "clearTimeout"
let id = setTimeout(() => Console.log("hello"), 100)
clearTimeout(id)
```
```js
var id = setTimeout(function (param) {
console.log("hello");
}, 100);
clearTimeout(id);
```
Clearly, `timerId` is a type that can only be created by `setTimeout`! Now we've guaranteed that `clearTimeout` _will_ be passed a valid ID. Whether it's a number under the hood is now a mere implementation detail.
Since `external`s are inlined, we end up with JS output as readable as hand-written JS.
## Global Modules
If you want to bind to a value inside a global module, e.g. `Math.random`, attach a `scope` to your `val` external:
```res example
@scope("Math") @val external random: unit => float = "random"
let someNumber = random()
```
```js
var someNumber = Math.random();
```
you can bind to an arbitrarily deep object by passing a tuple to `scope`:
```res example
@val @scope(("window", "location", "ancestorOrigins"))
external length: int = "length"
```
```js
// Empty output
```
This binds to `window.location.ancestorOrigins.length`.
## Special Global Values
Global values like `__filename` and `__DEV__` don't always exist; you can't even model them as an `option`, since the mere act of referring to them in ReScript (then compiled into JS) would trigger the usual `Uncaught ReferenceError: __filename is not defined` error in e.g. the browser environment.
For these troublesome global values, ReScript provides a special approach: `%external(a_single_identifier)`.
```res example
switch %external(__DEV__) {
| Some(_) => Console.log("dev mode")
| None => Console.log("production mode")
}
```
```js
var match = typeof __DEV__ === "undefined" ? undefined : __DEV__;
if (match !== undefined) {
console.log("dev mode");
} else {
console.log("production mode");
}
```
That first line's `typeof` check won't trigger a JS ReferenceError.
Another example:
```res example
switch %external(__filename) {
| Some(f) => Console.log(f)
| None => Console.log("non-node environment")
};
```
```js
var match = typeof (__filename) === "undefined" ? undefined : (__filename);
if (match !== undefined) {
console.log(match);
} else {
console.log("non-node environment");
}
```