ReScript Documentation

website·Indexed 35 days ago

https://rescript-lang.org/

A robustly typed language that compiles to efficient, human-readable JavaScript. Documentation covers the language overview, type system, JavaScript interop, the build system, and integration with React and JSX.

Tokens
97.9K
Snippets
669
Records
866
Agent score
68%

What's inside ReScript

  1. Overview of ReScript Standard Libraries

    ReScript provides several libraries for different use cases:

    • Stdlib: The built-in standard library for day-to-day programming. It often compiles directly to equivalent JavaScript APIs (e.g., Array.map in ReScript becomes .map() in JS).
    • WebAPI: An experimental library for interacting with Web APIs such as fetch, navigator, and localStorage.
    • Belt: Provides immutable collections and extra helper functions not available in the Stdlib or JavaScript.
    • Dom: Deprecated DOM-related types and modules; users should migrate to the WebAPI library.
  2. Overview of ReScript Standard Libraries

    ReScript provides several libraries for different needs:

    • Stdlib: The built-in standard library for day-to-day programming. It maps closely to the JavaScript API (e.g., Array.map compiles to .map()).
    • WebAPI: An experimental library for interacting with Web APIs like fetch, navigator, and localStorage.
    • Belt: Provides immutable collections and helper functions not available in Stdlib or JavaScript.
    • Dom: Deprecated DOM-related types; users should migrate to the WebAPI library.
  3. Understand ReScript type system fundamentals

    ReScript features a type system with the following characteristics:

    • Strong: Types cannot change into other types at runtime.
    • Static: Types are erased after compilation and do not exist at runtime, ensuring no performance penalty.
    • Sound: The type system is guaranteed to be correct; it does not make guesses about types.
    • Inferred: The compiler can deduce types from values, reducing the need for manual annotations.
    • Fast: The type checker is optimized for high-speed build times.
  4. Represent React elements with React.element

    The React.element type is the fundamental type for representing React elements. In ReScript, JSX does not automatically convert strings to React.element; you must explicitly convert primitive types using the React module functions to avoid type errors.
    // This will NOT type-check
    <div> Hello World </div>
    
    // Correct way: use React.string
    <div> {React.string("Hello World")} </div>
  5. Understand ReScript type system characteristics

    ReScript features a type system with the following properties:

    • Strong: Types cannot change into other types at runtime.
    • Static: Types are erased after compilation and do not impact runtime performance.
    • Sound: The type system is guaranteed to be correct; it does not make guesses.
    • Inferred: The compiler automatically deduces types from values, reducing the need for manual type annotations.
    // Type inference in action
    let score = 10 // inferred as int
    let add = (a, b) => a + b // inferred as (int, int) => int
  6. Understand ReScript Type System Basics

    ReScript features a strong, static, and sound type system. Types are erased after compilation and do not exist at runtime. The compiler uses type inference to deduce types from values, but developers can provide explicit type annotations for clarity or constraint. Type aliases can be created to give a different name to an existing type.
    // Type Inference
    let score = 10 // inferred as int
    let add = (a, b) => a + b // inferred as (int, int) => int
    
    // Type Annotation
    let score: int = 10
    let add = (x: int, y: int) : int => x + y
    
    // Type Alias
    type scoreType = int
    let x: scoreType = 10
  7. ReScript syntax quick reference for JavaScript developers

    ReScript shares similarities with JavaScript but has key differences in how it handles state, types, and control flow:

    • Immutability: let bindings are immutable by default. Use ref for mutable state.
    • Null Safety: ReScript avoids null and undefined in favor of the option type (Some(value) or None).
    • Collections: Arrays are homogeneous (all elements must be the same type). Use tuples for mixed fixed-size data.
    • Typing: Records are typed and not ad-hoc objects.
    • Expressions: Conditionals (if-else) and blocks return values.
    • Pattern Matching: switch is used for destructuring and exhaustive branching.
    // Immutable binding
    let x = 5
    
    // Mutable state
    let x = ref(5)
    
    // String concatenation
    let greeting = "hello " ++ name
    
    // Option type
    let value = Some("hello")
    
    // Record
    let point = {x: 30, y: 20}
    
    // Tuple
    let user = (1, "Bob", true)
    
    // Function
    let add = (a, b) => a + b
    
    // Block (returns last expression)
    { 
      let x = 1;
      x + 1 
    }
  8. Use Polymorphic Variants for structural typing and JS interop

    Polymorphic variants (poly variants) are structurally typed alternatives to regular variants. They start with a # and do not require an explicit type definition as the type is inferred from usage. They are particularly useful for JavaScript interop because they compile directly to JS strings or numbers without the overhead of nominal type wrappers.
    let myColor = #red
    let myLabel = #"aria-hidden"
    let myNumber = #7
  9. Understand the ReScript compilation and build model

    ReScript maps one .res or .resi source file to exactly one JavaScript output file. Because of this 1:1 mapping, it integrates easily with existing JS build tools (like Webpack watchers) without requiring a specialized loader. It is recommended to check in the generated JS files to allow for visual diffs of changes and to enable teammates to hot-patch JS in emergencies without needing to know ReScript.
  10. Use Generalized Algebraic Data Types (GADTs) for type-specific variants

    Generalized Algebraic Data Types (GADTs) allow you to add extra type-specificity to variants, enabling individual cases of a variant to have different types. This is useful when you need to:

    1. Distinguish between different members of a variant at the type level (subtyping).
    2. Hide type information in a type-safe way without using casts.
    3. Create functions that return different types based on the input provided (using the GADT as a type witness).

    Note: GADTs can make type errors more difficult to understand and may require more explicit type annotations as the compiler's ability to infer types is reduced.

  11. ReScript Compiler and JS Interop Characteristics

    ReScript compiles to optimized, human-readable JavaScript that is compatible with standard web tools (bundlers, test runners, Node.js).

    • Performance: Generates JS that leverages JIT optimizations (hidden classes, inline caching).
    • Structure: Maps one source file to one JS output file, preserving code structure for easier debugging and tool integration.
    • Dead Code Elimination: Performs purity analysis to eliminate unused functions and modules, and generates code compatible with Rollup and Closure Compiler.
  12. Use Scoped Polymorphic Types for JavaScript API Interop

    Scoped Polymorphic Types in ReScript allow functions to handle arguments of any type within a specific scope. This is primarily used when interfacing with JavaScript APIs, enabling functions to accept diverse data types while maintaining ReScript's strong type checking.