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.
  • 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.
  • 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.

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.
  • 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.
  • 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.
  • Use ordinary references and explicit reads/updates instead of Int.Ref or custom externals using %incr, %decr, %refget, %function_arity, %succint, or %predint.
  • 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.
  • Replace %re with regexp literals in both the manual and syntax lookup. Keep the removed form only in migration explanations.
  • Replace @taggedTemplate externals with taggedTemplate<'param, 'output>. Lift ReScript tag functions with TaggedTemplate.make; ordinary functions cannot be used directly as backtick tags.
  • 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.
  • 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.

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.
  • 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.
  • Add dictionary-spread examples, including how later entries override earlier keys.
  • Add record-rest patterns and explain that they collect fields not explicitly destructured. Show the required record type annotation on the rest pattern.
  • 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.
  • 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.
  • 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.
  • 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.
  • Show String.localeCompare with optional ~locales and ~options, rather than implying comparisons always use the default locale.
  • 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.
  • 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.
  • 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.
  • 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.
  • Update any documentation-generator integrations using rescript-tools doc: structured function information now preserves labels, optionality, and nested types, changing the RescriptTools.Docgen schema.

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.
  • 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.
  • 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.
  • Compile every positive ReScript example. Mark intentionally invalid
    examples explicitly, and explain the expected error.
  • Regenerate displayed JavaScript and preserved JSX with
    yarn test --update; do not hand-edit generated output.
  • 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.
  • Keep historical release notes and blog posts historically accurate instead
    of silently presenting them as current v13 tutorials.
  • 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

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions