Skip to content

v13 Language Documentation (AI Generated) #1476

Open

Description

@aspeddro

Generated by Codex

Scope: 13.0.0-alpha.1 through 13.0.0-alpha.6, inclusive. This is an
editorial checklist for the language manual, React documentation, and syntax
lookup, focused on people learning ReScript for the first time.

Teach the current API first. Put old syntax and upgrade instructions in clearly
labeled migration notes. Unchecked boxes mean the documentation needs review;
they do not mean the feature is unimplemented or undocumented.

The release attribution below follows the compiler changelog supplied for this
update. Internal compiler refactors are omitted unless they affect a reader's
code, build, or tools. Alpha.2 has no separately listed breaking changes or new
features, but its pattern-matching fixes are covered below.

1. Installation and Project Setup

Primary pages: manual/installation.mdx, manual/build-overview.mdx, and
manual/build-configuration.mdx under apps/docs/markdown-pages/docs/.

  • Remove rescript-legacy from introductory workflows. Teach the modern rescript build, rescript watch, and rescript clean commands.
  • State that compiler v13 requires Node.js 22 or newer; Node.js 20 is unsupported. Keep this distinct from any higher Node.js requirement imposed by website tooling.
    • Existing Node.js 22 minimum documented in #1135.
    • Breaking, alpha.5
    • PR #8401
  • Use dependencies, dev-dependencies, and compiler-flags. Remove the obsolete bs-dependencies, bs-dev-dependencies, bsc-flags, and external-stdlib configuration options from current examples.
  • Explain that esmodule is the default. Replace es6 and es6-global, and show distinct suffixes if a project emits multiple module formats.
  • Remove --dev, --create-sourcedirs, build -w, and bsc -uncurried from command examples. Use rescript watch for watching.
    • Current CLI documentation: #1456, brought into v13 by #1459. The old command remains only in explicitly historical migration examples.
    • Breaking, alpha.1
    • PR #8202
    • PR #8201
  • Prefer rescript.json, but do not claim bsconfig.json is unsupported: alpha.1 removed it and alpha.4 restored compatibility.
  • Explain that js-post-build runs from the directory containing its rescript.json, receives the actual output path for the selected in-source setting, and exposes stdout/stderr.
    • Post-build working directory, output-path handling, and stdout/stderr forwarding documented in #1456; included in v13 via #1459.
    • Changed behavior, alpha.1
    • PR #8190
    • PR #8195

Example starting point for an alpha.6 project:

npm install --save-dev rescript@13.0.0-alpha.6
npx rescript build
npx rescript watch
{
  "name": "learning-rescript",
  "sources": [{ "dir": "src", "subdirs": true }],
  "package-specs": { "module": "esmodule" },
  "dependencies": []
}

2. Breaking Syntax and API Changes

Primary pages: manual/primitive-types.mdx, manual/function.mdx,
manual/object.mdx, manual/bind-to-global-js-values.mdx,
manual/tagged-templates.mdx, and the corresponding syntax-lookup entries.

  • Use modern standard-library modules instead of Js. Explain replacements in context, such as Console, JSON, Promise, Nullable, and JsExn, rather than teaching the removed namespace.
    • Examples and standard-library replacements updated in #1473.
    • Breaking, alpha.6
    • PR #8531
  • Use standard-library APIs in beginner examples. Explain in migration notes that existing Belt users must install @rescript/belt and add it to rescript.json dependencies.
    • Partial: beginner examples migrated in #1473; explicit @rescript/belt installation/migration guidance is still missing.
    • Breaking, alpha.6
    • PR #8554
  • Replace Belt APIs returning undefined, such as getUndefined, with their option-returning counterparts when documenting migration of existing Belt code.
  • Remove examples using Char, removed unsafe Obj operations, legacy Pervasives helpers, or Array.unsafe_get. Document supported APIs such as Int.toString, panic, and safe array access where appropriate.
    • Legacy helper replacements and current examples: #1473.
    • Breaking, alpha.6
    • PR #8564
  • Use ordinary references and explicit reads/updates instead of Int.Ref or custom externals using %incr, %decr, %refget, %function_arity, %succint, or %predint.
    • Current reference examples and removal of obsolete API usage verified by the alpha.6 example/output validation in #1473.
    • Breaking, alpha.6
    • PR #8616
    • PR #8608
  • Explain strict numeric parsing: remove explicit radix arguments, show accepted hexadecimal/binary/exponential forms, and handle parsing failures with option. bindings. Show optional properties on globalThis for globals that may be absent; explain that bundler-replaced identifiers and CommonJS module variables are not necessarily global-object properties.
    • Partial: optional globalThis bindings and bundler/CommonJS caveats are documented in #1473. Strict numeric-parsing guidance remains to be added.
    • Breaking, alpha.1
    • PR #8129
    • PR #8376
  • Replace %re with regexp literals in both the manual and syntax lookup. Keep the removed form only in migration explanations.
    • Partial: runnable examples use regexp literals after #1473. Removal of the deprecated %re catalog entry is pending in #1478 (not merged yet).
    • Breaking, alpha.6
    • PR #8634
  • Replace @taggedTemplate externals with taggedTemplate<'param, 'output>. Lift ReScript tag functions with TaggedTemplate.make; ordinary functions cannot be used directly as backtick tags.
    • Documentation and binding/tag examples updated in #1473.
    • Breaking, alpha.5
    • PR #8461
  • Explain that tagged-template patterns are rejected. Use ordinary literal patterns for literal matching.
  • Update string/documentation examples to use valid UTF-8 and valid escapes; malformed escapes now produce errors instead of unreliable output.
    • Positive examples and generated output validated against alpha.6, including corrected escaping, in #1473.
    • Breaking, alpha.6
    • PR #8606
  • Teach object-field write access through bare @set. Remove object-type @get attributes and @set({no_get: ...}); express nullable property types directly. Clarify that this change concerns attributes on object fields, not valid @get external bindings.
  • Explain the async-method distinction: @this this => async arg => ... returns an async function; @this async (this, arg) => ... is an async method receiving both parameters.
  • Teach ordinary uncurried function syntax. The legacy (. ...) form was removed in alpha.1 but restored with a deprecation warning in alpha.4; do not describe it as still rejected.
    • Current ordinary-function examples validated/refreshed against alpha.6 in #1473; the manual does not claim the deprecated call syntax is rejected.
    • Compatibility reversal, alpha.4
    • PR #8211
    • PR #8383

Example: Parse Numbers and Update a Reference

let hexadecimal = Int.fromString("0x2a")
let binary = Int.fromString("0b101010")
let exponential = Float.fromString("1.25e2")
let invalid = Int.fromString("12tail")

let count = ref(0)
count := count.contents + 1

Example: Optional Globals and Regexp Literals

@scope("globalThis")
external appVersion: option<string> = "__APP_VERSION__"

switch appVersion {
| Some(version) => Console.log(version)
| None => Console.log("Version not provided")
}

let startsWithHello = /^hello/i
let matches = startsWithHello->RegExp.test("Hello world")

Example: Explicitly Settable Object Fields

type counter = {@set "value": int}

let increment = (counter: counter) => {
  counter["value"] = counter["value"] + 1
}

3. New Language Features

Primary pages: manual/control-flow.mdx, manual/dict.mdx,
manual/pattern-matching-destructuring.mdx, manual/tagged-templates.mdx, and
manual/bind-to-js-function.mdx.

  • Teach break and continue inside loops and warn that they can no longer be variable names. Remove statements that ReScript has no loop-control keywords.
    • Documentation and examples added in #1473.
    • New and breaking, alpha.4
    • PR #8348
  • Teach for item of items and for await item of items. Explain iterable versus async-iterable inputs, the array convenience case, and the variable-or-underscore loop binding restriction.
    • Synchronous/asynchronous iteration documentation and examples added in #1473.
    • New, alpha.4
    • PR #7887
  • Add dictionary-spread examples, including how later entries override earlier keys.
    • Dictionary-spread examples and overwrite behavior added in #1473.
    • New, alpha.4
    • PR #8369
  • Add record-rest patterns and explain that they collect fields not explicitly destructured. Show the required record type annotation on the rest pattern.
    • Record-rest patterns, explicit rest types, and restrictions documented in #1473.
    • New, alpha.5
    • PR #8317
  • Introduce first-class tagged-template values with separate examples for a JavaScript external and a ReScript-created tag. Explain their input and output type parameters.
    • External and ReScript-created tagged-template examples updated in #1473.
    • New, alpha.5
    • PR #8461
  • Show UTF-16 surrogate-pair escapes in ordinary string literals.
  • Explain that inferred labeled functions can receive labels in any order. Keep labeled parameters distinct from positional parameters.
    • The existing inferred labeled-function example calls labels in reverse order; its alpha.6 compilation/output is validated in #1473.
    • New, alpha.6
    • PR #8547
  • Add inline record types to external-binding examples.
  • Show dynamic imports of @scope externals in the lazy-loading documentation; the imported value follows the complete property path.

Example: Iterate, Skip, and Stop

for number of [1, 2, 3, 4, 5] {
  if number == 2 {
    continue
  }
  if number == 4 {
    break
  }
  Console.log(number)
}
let printMessages = async (messages: asyncIterable<string>) => {
  for await message of messages {
    Console.log(message)
  }
}

Example: Dictionary Spreads and Record Rest

let defaults = dict{"theme": "light", "language": "en"}
let settings = dict{...defaults, "theme": "dark"}
type user = {name: string, age: int, active: bool}
type userDetails = {age: int, active: bool}
let user = {name: "Ada", age: 30, active: true}
let {name, ...userDetails as details} = user
let age = details.age

Example: Bind and Create Tagged Templates

This external describes a JavaScript tag function; it does not use a decorator:

type result = {exitCode: int}

@module("bun")
external shell: taggedTemplate<string, promise<result>> = "$"

let listFiles = filename => shell`ls ${filename}`

A ReScript function must be lifted into a tagged-template value:

let text = TaggedTemplate.make((segments, values) =>
  values->Array.reduceWithIndex(segments[0]->Option.getOr(""), (acc, value, index) =>
    acc ++ value ++ (segments[index + 1]->Option.getOr(""))
  )
)

let name = "Ada"
let greeting = text`Hello ${name}!`

Example: Reordered Labels and Unicode Escapes

let fullName = (~first, ~last) => first ++ " " ++ last
let name = fullName(~last="Lovelace", ~first="Ada")
let smilingFace = "\uD83D\uDE00"

4. Standard-Library Additions and Semantic Changes

Primary pages: manual/array-and-list.mdx, manual/dict.mdx,
manual/primitive-types.mdx, and the standard-library API reference.

  • Add practical examples for Array.zip, Array.unzip, Array.zipBy, and Array.partition.
  • Document Dict.assignMany, Dict.concat, Dict.concatMany, Dict.concatAll, and Array.concatAll; distinguish mutating assignment from operations that return a result.
    • Covered by the published Dict and Array API documentation, including mutation versus fresh results; v13 publication selection: #1458.
    • New, alpha.4
    • PR #8364
  • Use List.includes for membership and List.some for custom predicates. Explain strict equality for lists versus SameValueZero for Array.includes, including their different NaN behavior and reference comparison for objects.
    • Covered by the published List and Array API descriptions/examples for predicates, equality, NaN, and object identity; v13 publication selection: #1458.
    • New, alpha.6
    • PR #8530
  • Show String.localeCompare with optional ~locales and ~options, rather than implying comparisons always use the default locale.
    • The published String API includes both ~locales and ~options examples; v13 publication selection: #1458.
    • New, alpha.3
    • PR #8287
  • Update Intl.Collator.compare examples to use Ordering.t (float); compare the result with zero rather than assuming an int or only the values -1 and 1.
    • The published Collator API returns Ordering.t and demonstrates Ordering.isLess; v13 publication selection: #1458.
    • Breaking, alpha.3
    • PR #8289
  • Explain that mutating a private mutable record field produces a configurable warning. Distinguish this warning from object-field @set requirements.

Example: Membership and Predicates

let names = list{"Ada", "Lin"}
let containsAda = names->List.includes("Ada")
let containsShortName = names->List.some(name => name->String.length < 4)

let pairs = Array.zip(["Ada", "Lin"], [1, 2])
let (even, odd) = Array.partition([1, 2, 3, 4], number => mod(number, 2) == 0)

5. React and JavaScript Interop

Primary pages: react/components-and-props.mdx, react/elements-and-jsx.mdx,
react/memo.mdx, manual/jsx.mdx, and manual/typescript-integration.mdx.

  • Explain that React.component<props>/Jsx.component<props> is distinct from a plain props => React.element function. Use @react.component, @react.componentWithProps, or React.component as appropriate.
    • Partial: component examples/conversions were adapted in #1473, but the "Beyond JSX" explanation still describes React.component as equivalent to a plain function.
    • Breaking, alpha.5
    • PR #8390
  • Explain that a curried implementation cannot satisfy an uncurried interface or be coerced to one. Include an intentional error and a corrected signature in the function/interoperability docs.
  • Review examples involving dynamic imports of externals with argument/result conversions; imports now honor the same FFI conversions as direct calls.
  • Document @res.hoistedFunction as an advanced interop feature: a nested module function can also receive a flat JavaScript export. Show the actual compiler-generated export name.
  • Review generated TypeScript examples against React 19 definitions.

Example: Record-Props Components

module Greeting = {
  type props = {name: string}

  @react.componentWithProps
  let make = (props: props) => <p>{React.string(`Hello ${props.name}`)}</p>
}

let element = <Greeting name="Ada" />

6. Build, Debugging, and Editor Features

Primary pages: manual/build-configuration.mdx,
manual/build-monorepo-setup.mdx, manual/source-maps.mdx, and
manual/editor-code-analysis.mdx.

  • Explain --prod for build, watch, and clean: it excludes dev dependencies and sources with "type": "dev".
  • Explain feature-gated source directories, dependency feature selection, --features, and transitive feature implications with a small optional-browser-module example.
  • Document watch output and --clear-screen. Also explain that ordinary builds can run while a watcher is active.
  • Explain linked, inline, and hidden source maps, including when sourcesContent embeds original source text.
    • Dedicated source-map documentation added in #1333, covering all three output modes and sourcesContent.
    • New, alpha.6
    • PR #8393
  • Document scoped @@live/@@dead annotations and glob patterns for reanalyze suppress/unsuppress configuration.
  • Remove reanalyze -reactive from commands; explain the now-default pipeline and stable diagnostic ordering.
  • Replace deprecated Stdlib_Error/Stdlib_Exn references with JsError/JsExn.
    • Current exception examples and alpha.6 output validated/refreshed in #1473; deprecated Stdlib_Error/Stdlib_Exn references are absent from current manual/React/lookup content.
    • Changed tooling, alpha.5
    • PR #8404
  • Update any documentation-generator integrations using rescript-tools doc: structured function information now preserves labels, optionality, and nested types, changing the RescriptTools.Docgen schema.
    • Partial: the website/compiler migration (#1472) and v13 API loading (#1458) have landed. Review of the new structured Docgen function metadata is still outstanding.
    • Breaking tooling, alpha.6
    • PR #8576

Example: Linked Source Maps

Add this property to rescript.json:

{
  "source-map-spec": {
    "enabled": "always",
    "mode": "linked",
    "sourcesContent": true
  }
}

linked emits a separate map referenced by the generated JavaScript. inline
embeds the map in the JavaScript. hidden emits a separate map without a
mapping comment.

7. Behavior Corrections Worth Explaining

These changes were listed as bug fixes, but they can invalidate older examples
or assumptions.

  • Ensure JSON and untagged-variant examples distinguish null, arrays, and objects correctly.
    • Current JSON/unboxed examples distinguish null, arrays, and dictionaries; runnable examples/output were validated in #1473 and the v13 JSON API reference is selected by #1458.
    • Alpha.2/alpha.3
    • PR #8253
    • PR #8279
  • Review explanations of argument evaluation and optional defaults: inlining preserves argument order, and each curried parameter group evaluates its defaults when that group is applied.
  • Explain that equivalent escaped string literals match the same runtime value; redundant patterns can now be reported consistently.
  • Review FFI examples whose return type aliases unit; aliases now receive the same unit-return handling as a direct unit annotation.
  • Do not describe potentially throwing array/string reads or bigint exponentiation as removable just because their result is unused.
    • Current prose makes no such removal claim; displayed output was regenerated and validated against alpha.6 in #1473.
    • Alpha.6
    • PR #8617
  • Use current diagnostics in error examples: function-arity mismatches, non-settable object fields, invalid @as payloads, and out-of-range constructor annotations now have more accurate errors.

8. Review and Publication Checklist

  • Check each topic against the alpha.6 compiler rather than assuming an
    earlier alpha's behavior still applies.
  • Put current, runnable syntax before historical migration notes.
  • Keep explanations understandable without prior knowledge of OCaml,
    compiler internals, or earlier ReScript versions.
  • Update the manual, React documentation, and matching syntax-lookup entries
    together.
    • Manual, React documentation, and syntax lookup updated together in #1473.
  • Compile every positive ReScript example. Mark intentionally invalid
    examples explicitly, and explain the expected error.
    • Validation in #1473: 190 pages checked with zero compilation errors or malformed blocks; intentional errors/excerpts are marked explicitly.
  • Regenerate displayed JavaScript and preserved JSX with
    yarn test --update; do not hand-edit generated output.
    • JavaScript and preserved JSX output tabs regenerated in #1473.
  • Run CI=1 yarn test without update mode and confirm there are no stale
    outputs, malformed blocks, compilation errors, broken links, or redirect
    failures.
  • Format changed Markdown/MDX and run git diff --check.
    • Changed MDX files formatted and git diff --cached --check passed in #1473.
  • Keep historical release notes and blog posts historically accurate instead
    of silently presenting them as current v13 tutorials.
    • #1473 updates current manual/React/lookup examples while preserving historical blog and release-post content.
  • Include the relevant compiler PR links when reviewing or publishing each
    documentation change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions