Repository navigation
v13 Language Documentation (AI Generated) #1476
Description
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-legacyfrom introductory workflows. Teach the modernrescript build,rescript watch, andrescript cleancommands. - 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.
- Breaking, alpha.5
- PR #8401
- Use
dependencies,dev-dependencies, andcompiler-flags. Remove the obsoletebs-dependencies,bs-dev-dependencies,bsc-flags, andexternal-stdlibconfiguration options from current examples. - Explain that
esmoduleis the default. Replacees6andes6-global, and show distinct suffixes if a project emits multiple module formats. - Remove
--dev,--create-sourcedirs,build -w, andbsc -uncurriedfrom command examples. Userescript watchfor watching. - Prefer
rescript.json, but do not claimbsconfig.jsonis unsupported: alpha.1 removed it and alpha.4 restored compatibility. - Explain that
js-post-buildruns from the directory containing itsrescript.json, receives the actual output path for the selectedin-sourcesetting, 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 asConsole,JSON,Promise,Nullable, andJsExn, rather than teaching the removed namespace.- Breaking, alpha.6
- PR #8531
- Use standard-library APIs in beginner examples. Explain in migration notes that existing Belt users must install
@rescript/beltand add it torescript.jsondependencies.- Breaking, alpha.6
- PR #8554
- Replace Belt APIs returning
undefined, such asgetUndefined, with their option-returning counterparts when documenting migration of existing Belt code.- Breaking, alpha.4
- PR #8377
- Remove examples using
Char, removed unsafeObjoperations, legacyPervasiveshelpers, orArray.unsafe_get. Document supported APIs such asInt.toString,panic, and safe array access where appropriate.- Breaking, alpha.6
- PR #8564
- Use ordinary references and explicit reads/updates instead of
Int.Refor 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 onglobalThisfor globals that may be absent; explain that bundler-replaced identifiers and CommonJS module variables are not necessarily global-object properties. - Replace
%rewith regexp literals in both the manual and syntax lookup. Keep the removed form only in migration explanations.- Breaking, alpha.6
- PR #8634
- Replace
@taggedTemplateexternals withtaggedTemplate<'param, 'output>. Lift ReScript tag functions withTaggedTemplate.make; ordinary functions cannot be used directly as backtick tags.- Breaking, alpha.5
- PR #8461
- Explain that tagged-template patterns are rejected. Use ordinary literal patterns for literal matching.
- Breaking, alpha.6
- PR #8606
- Update string/documentation examples to use valid UTF-8 and valid escapes; malformed escapes now produce errors instead of unreliable output.
- Breaking, alpha.6
- PR #8606
- Teach object-field write access through bare
@set. Remove object-type@getattributes and@set({no_get: ...}); express nullable property types directly. Clarify that this change concerns attributes on object fields, not valid@getexternal bindings.- Breaking, alpha.6
- PR #8597
- Explain the async-method distinction:
@this this => async arg => ...returns an async function;@this async (this, arg) => ...is an async method receiving both parameters.- Breaking, alpha.6
- PR #8566
- 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 + 1Example: 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
breakandcontinueinside loops and warn that they can no longer be variable names. Remove statements that ReScript has no loop-control keywords.- New and breaking, alpha.4
- PR #8348
- Teach
for item of itemsandfor await item of items. Explain iterable versus async-iterable inputs, the array convenience case, and the variable-or-underscore loop binding restriction.- New, alpha.4
- PR #7887
- Add dictionary-spread examples, including how later entries override earlier keys.
- 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.
- 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.
- New, alpha.5
- PR #8461
- Show UTF-16 surrogate-pair escapes in ordinary string literals.
- New, alpha.6
- PR #8606
- Explain that inferred labeled functions can receive labels in any order. Keep labeled parameters distinct from positional parameters.
- New, alpha.6
- PR #8547
- Add inline record types to external-binding examples.
- New, alpha.3
- PR #8304
- Show dynamic imports of
@scopeexternals in the lazy-loading documentation; the imported value follows the complete property path.- New, alpha.6
- PR #8582
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.ageExample: 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, andArray.partition.- New, alpha.1
- PR #8244
- Document
Dict.assignMany,Dict.concat,Dict.concatMany,Dict.concatAll, andArray.concatAll; distinguish mutating assignment from operations that return a result.- New, alpha.4
- PR #8364
- Use
List.includesfor membership andList.somefor custom predicates. Explain strict equality for lists versus SameValueZero forArray.includes, including their differentNaNbehavior and reference comparison for objects.- New, alpha.6
- PR #8530
- Show
String.localeComparewith optional~localesand~options, rather than implying comparisons always use the default locale.- New, alpha.3
- PR #8287
- Update
Intl.Collator.compareexamples to useOrdering.t(float); compare the result with zero rather than assuming anintor only the values -1 and 1.- Breaking, alpha.3
- PR #8289
- Explain that mutating a private mutable record field produces a configurable warning. Distinguish this warning from object-field
@setrequirements.- New behavior, alpha.5
- PR #8366
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 plainprops => React.elementfunction. Use@react.component,@react.componentWithProps, orReact.componentas appropriate.- 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.
- Changed behavior, alpha.6
- PR #8559
- Review examples involving dynamic imports of externals with argument/result conversions; imports now honor the same FFI conversions as direct calls.
- Changed behavior, alpha.6
- PR #8582
- Document
@res.hoistedFunctionas an advanced interop feature: a nested module function can also receive a flat JavaScript export. Show the actual compiler-generated export name.- New, alpha.6
- PR #8402
- Review generated TypeScript examples against React 19 definitions.
- Changed tooling, alpha.5
- PR #8501
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
--prodforbuild,watch, andclean: it excludes dev dependencies and sources with"type": "dev".- New, alpha.4
- PR #8347
- Explain feature-gated source directories, dependency feature selection,
--features, and transitive feature implications with a small optional-browser-module example.- New, alpha.4
- PR #8379
- 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
sourcesContentembeds original source text.- New, alpha.6
- PR #8393
- Document scoped
@@live/@@deadannotations and glob patterns for reanalyze suppress/unsuppress configuration. - Remove
reanalyze -reactivefrom commands; explain the now-default pipeline and stable diagnostic ordering.- Breaking, alpha.6
- PR #8648
- Replace deprecated
Stdlib_Error/Stdlib_Exnreferences withJsError/JsExn.- 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 theRescriptTools.Docgenschema.- 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. - 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.
- Alpha.6
- PR #8606
- Review FFI examples whose return type aliases
unit; aliases now receive the same unit-return handling as a directunitannotation.- Alpha.6
- PR #8581
- Do not describe potentially throwing array/string reads or bigint exponentiation as removable just because their result is unused.
- Alpha.6
- PR #8617
- Use current diagnostics in error examples: function-arity mismatches, non-settable object fields, invalid
@aspayloads, 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 testwithout 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.
Activity
%externalwith appropriate explicit #1477%externalwith appropriate explicit #1477