ReScript for JavaScript Developers
If you already write JavaScript, ReScript should feel familiar quickly. This page is a compact syntax guide for the main differences you should be aware of.
For a guided migration workflow, see Converting from JS.
What to know first
letbindings are immutable by default. See Let Binding and Mutation.ReScript does not use
nullandundefinedas normal control flow. Reach foroptioninstead. See Null, Undefined and Option.Arrays must contain values of the same type. See Array and List and Tuple.
Records are not ad-hoc JS objects; they have known field names and types. See Record and Object.
Conditionals and blocks return values, so expression-oriented code is common. See If-Else & Loops.
Pattern matching replaces many ad-hoc
ifor property-check branches. See Pattern Matching / Destructuring.
Quick reference
| Topic | ReScript | Notes for JavaScript developers |
|---|---|---|
| Semicolons | let x = 1 | Semicolons are not required. See Overview. |
| Comments | //, /* */, /** */ | Familiar syntax, including doc comments. See Overview. |
| Variables | let x = 5 | let creates an immutable binding. See Let Binding. |
| Mutation | let x = ref(5) | Mutable state is explicit through ref or mutable fields. See Mutation. |
| Strings | "hello" | Strings use double quotes. See Primitive Types. |
| String concatenation | "hello " ++ name | ReScript uses ++ for strings. See Primitive Types. |
| Interpolation | `hello ${name}` | Template strings work similarly. See Primitive Types. |
| Equality | ===, !==, ==, != | No coercive equality. == and != are structural. See Equality and Comparison. |
| Numbers | 3, 3.14, 2.0 * 3.0 | Arithmetic operators work for both int and float. See Primitive Types. |
| Records | {x: 30, y: 20} | Similar object syntax, but records are typed. See Record. |
| Arrays | [1, 2, 3] | Arrays are homogeneous. See Array and List. |
| Mixed fixed-size data | (1, "Bob", true) | Use tuples instead of heterogeneous arrays. See Tuple. |
| Missing values | option<'a> | Use Some(value) and None instead of null and undefined. See Null, Undefined and Option. |
| Functions | let add = (a, b) => a + b | Familiar arrow-style syntax. See Function. |
| Blocks | { let x = 1; x + 1 } | The last expression is returned implicitly. See Overview. |
| Conditionals | if cond {a} else {b} | if is an expression. See If-Else & Loops. |
| Pattern matching | switch value { ... } | Use switch for destructuring and exhaustive branching. See Pattern Matching / Destructuring. |
| Destructuring | let {a, b} = data | Works for records, arrays, tuples, and more. See Pattern Matching / Destructuring. |
| Loops | for i in 0 to 10 {} | for and while exist, but collection transforms are also common. See If-Else & Loops. |
| Exceptions | throw(MyException(...)) | throw and try exist, but typed data flow is preferred where possible. See Exception. |
| JSX | <Comp message /> | JSX is supported directly, with a few ReScript conventions. See JSX. |
Where to Go Next
For a broader syntax reference, see Overview.
For a migration workflow inside an existing codebase, see Converting from JS.
For JavaScript interop, see Interop Cheatsheet.
For importing and exporting JS modules, see Import from Export to JS.
For binding to JS objects and functions, see Bind to JS Object and Bind to JS Function.