Docs / Language Manual / Primitive Types
Edit

Primitive Types

ReScript comes with the familiar primitive types like string, int, float, etc.

String

ReScript strings are delimited using double quotes (single quotes are reserved for the character type below).

ReScriptJS Output
let greeting = "Hello world!"
let multilineGreeting = "Hello
 world!"

To concatenate strings, use ++:

ReScriptJS Output
let greetings = "Hello " ++ "world!"

String Interpolation

There's a special syntax for string that allows

  • multiline string just like before

  • no special character escaping

  • Interpolation

ReScriptJS Output
let name = "Joe"

let greeting = `Hello
World
👋
${name}
`

This is just like JavaScript's backtick string interpolation, except without needing to escape special characters.

Usage

See the familiar String API in the API docs. Since a ReScript string maps to a JavaScript string, you can mix & match the string operations in all standard libraries.

Tips & Tricks

You have a good type system now! In an untyped language, you'd often overload the meaning of string by using it as:

  • a unique id: var BLUE_COLOR = "blue"

  • an identifier into a data structure: var BLUE = "blue" var RED = "red" var colors = [BLUE, RED]

  • the name of an object field: person["age"] = 24

  • an enum: if (audio.canPlayType() === 'probably') {...} (ಠ_ಠ)

  • other crazy patterns you'll soon find horrible, after getting used to ReScript's alternatives.

The more you overload the poor string type, the less the type system (or a teammate) can help you! ReScript provides concise, fast and maintainable types & data structures alternatives to the use-cases above (e.g. variants, in a later section).

Char

ReScript has a type for a string with a single letter:

ReScriptJS Output
let firstLetterOfAlphabet = 'a'

Note: Char doesn't support Unicode or UTF-8 and is therefore not recommended.

To convert a String to a Char, use String.get("a", 0). To convert a Char to a String, use String.make(1, 'a').

Regular Expression

ReScript regular expressions compile cleanly to their JavaScript counterpart:

ReScriptJS Output
let r = %re("/b/g")

A regular expression like the above has the type Re.t. The Re module contains the regular expression helpers you have seen in JS.

Boolean

A ReScript boolean has the type bool and can be either true or false. Common operations:

  • &&: logical and.

  • ||: logical or.

  • !: logical not.

  • <=, >=, <, >

  • ==: structural equal, compares data structures deeply. (1, 2) == (1, 2) is true. Convenient, but use with caution.

  • ===: referential equal, compares shallowly. (1, 2) === (1, 2) is false. let myTuple = (1, 2); myTuple === myTuple is true.

  • !=: structural unequal.

  • !==: referential unequal.

ReScript's true/false compiles into a JavaScript true/false.

Integers

32-bits, truncated when necessary. We provide the usual operations on them: +, -, *, /, etc. See Int for helper functions.

Be careful when you bind to JavaScript numbers! Since ReScript integers have a much smaller range than JavaScript numbers, data might get lost when dealing with large numbers. In those cases it’s much safer to bind the numbers as float. Be extra mindful of this when binding to JavaScript Dates and their epoch time.

To improve readability, you may place underscores in the middle of numeric literals such as 1_000_000. Note that underscores can be placed anywhere within a number, not just every three digits.

Floats

Float requires other operators: +., -., *., /., etc. Like 0.5 +. 0.6. See Float for helper functions.

As with integers, you may use underscores within literals to improve readability.

Int-to-Float Coercion

int values can be coerced to float with the :> (type coercion) operator.

ReScriptJS Output
let result = (1 :> float) +. 2.

Big Integers (experimental)

Since 11.1

For values which are too large to be represented by Int or Float, there is the bigint primitive type. We provide the usual operations on them: +, -, *, /, etc. See BigInt for helper functions.

A bigint number is denoted by a trailing n like so: 42n.

As bigint is a different data type than int, it's necessary to open the corresponding module to overload the operators.

ReScriptJS Output
open! Js.BigInt

let a = 9007199254740991n + 9007199254740991n
let b = 2n ** 2n

It also supports all the bitwise operations, except unsigned shift right (>>>), which is not supported by JS itself for bigints.

ReScriptJS Output
open! Js.BigInt

let a = land(1n, 1n)
let b = lor(1n, 1n)
let c = lxor(1n, 1n)
let d = lnot(1n)
let e = lsl(1n, 1n)
let f = asr(1n, 1n)

It can also be pattern-matched.

ReScriptJS Output
let bigintValue = 1n

switch bigintValue {
| 1n => Console.log("Small bigint")
| 100n => Console.log("Larger bigint")
| _ => Console.log("Other bigint")
}

Unit

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