Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions pages/docs/manual/latest/bind-to-js-function.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,24 @@ testIntType(21);

`onClosed` compiles to `0`, `onOpen` to `20` and `inBinary` to **`21`**.

## Unknown for type safety

It is best practice to inspect data received from untrusted external functions to ensure it contains what you expect. This helps avoid run-time crashes and unexpected behavior. If you're certain about what an external function returns, simply assert the return value as `string` or `array<int>` or whatever you want it to be. Otherwise use `unknown`. The ReScript type system will prevent you from using an `unknown` until you first inspect it and "convert" it using JSON parsing utilities or similar tools.

Consider the example below of two external functions that access the value of a property on a JavaScript object. `getPropertyUnsafe` returns an `'a`, which means "anything you want it to be." ReScript allows you to use this value as a `string` or `array` or any other type. Quite convenient! But if the property is missing or contains something unexpected, your code might break. You can make the binding more safe by changing `'a` to `string` or `option<'a>`, but this doesn't completely eliminate the problem.

The `getPropertySafe` function returns an `unknown`, which could be `null` or a `string` or anything else. But ReScript prevents you from using this value inappropriately until it has been safely parsed.

```res example
@get_index external getPropertyUnsafe: ({..}, string) => 'a = ""
@get_index external getPropertySafe: ({..}, string) => unknown = ""

let person = {"name": "Bob", "age": 12}

let greeting1 = "Hello, " ++ getPropertyUnsafe(person, "name") // works (this time!)
// let greeting2 = "Hello, " ++ getPropertySafe(person, "name") // syntax error
```

## Special-case: Event Listeners

One last trick with polymorphic variants:
Expand Down
14 changes: 13 additions & 1 deletion pages/docs/manual/latest/primitive-types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,16 @@ As with integers, you may use underscores within literals to improve readability

## Unit

The `unit` type has a single value, `()`. It compiles to JavaScript's `undefined`. It's a dummy type used as a placeholder in various places. You won't need it until you see it.
The `unit` type indicates the absence of a specific value. It has only a single value, `()`, which acts as a placeholder when no other value exists or is needed. It compiles to JavaScript's `undefined` and resembles the `void` type in languages such as C++. What's the point of such a type?

Consider the `Math.random` function. Its type signature is `unit => float`, which means it receives a `unit` as input and calculates a random `float` as output. You use the function like this - `let x = Math.random()`. Notice `()` as the first and only function argument.

Imagine a simplified `Console.log` function that prints a message. Its type signature is `string => unit` and you'd use it like this `Console.log("Hello!")`. It takes a string as input, prints it, and then returns nothing useful. When `unit` is the output of a function it means the function performs some kind of side-effect.

## Unknown

The `unknown` type represents values with contents that are a mystery or are not 100% guaranteed to be what you think they are. It provides type-safety when interacting with data received from an untrusted source. For example, suppose an external function is supposed to return a `string`. It might. But if the documentation is not accurate or the code has bugs, the function could return `null`, an `array`, or something else you weren't expecting.

The ReScript type system helps you avoid run-time crashes and unpredicatable behavior by preventing you from using `unknown` in places that expect a `string` or `int` or some other type. The ReScript core libraries also provide utility functions to help you inspect `unknown` values and access their contents. In some cases you may need a JSON parsing library to convert `unknown` values to types you can safely use.

Consider using `unknown` when receiving data from [external JavaScript functions](/docs/manual/latest/bind-to-js-function)