Skip to content

Restrictions and reserved syntax

This page lists unsupported syntax, reserved names and runtime requirements for .tsi files.

  • ask and with are reserved words in .tsi. ask stays legal as a member or property name (obj.ask); using it as a plain identifier is NOLA1003.
  • infer is contextual: a keyword only directly before function at statement or export position. T extends infer U in a conditional type is untouched.
  • Names starting with __nola are used by generated code. Declaring one can shadow a generated binding and break the program without a diagnostic. Avoid these names and use the public Nola syntax instead of calling generated helpers.
// not-checked — WRONG: emitted code, not a user-facing API
export infer function read(.doc: string) {
const wrong = await __nola.ask(__nola.intents.ExtractIntent({ instruction: "the value" }), __frame);
return wrong;
}
// read.tsi — RIGHT
export infer function read(.doc: string) {
const v = ask `the value`: string;
return v;
}

Syntax that is reserved for a later version

Section titled “Syntax that is reserved for a later version”

The following forms are unsupported. The table shows the error to expect and, where available, the supported alternative.

You write What happens
async infer function f(…) parse error — an infer function is never async in source; await is already legal in its body
export default infer function f(…) does not parse — export by name and import the name
infer on a method, arrow function or function expression plain parse error (NOLA1001) — infer is a keyword only before function at statement/export position
infer function* (generator), a marker on a class method, or a bodiless infer function NOLA1004 — reserved
fn(..) — the bare derive-all call NOLA1004
var .x = … — a var contextual binding NOLA1014 — write const .x or let .x (Contextual bindings)
. on a destructuring pattern or a defaulted parameter NOLA1011 — use a plain identifier parameter
a marker between a function’s name and its parameters — infer function name`…`() / function name`…`() NOLA1019 (reserved) / NOLA1007 — write the text as a context statement in the body
an operator or an arrow after a value in a context statement — `total` a + b NOLA1020 — wrap the expression in parentheses
a context statement outside a scope body — in a plain function, a callback, a static block, or as the unbraced body of an if or a loop NOLA2017 — no ask can carry it there; move it into the scope body, or add braces to the if or loop

Other proposed forms also remain unsupported: abstract functions, type and interface intents, ask if, ask for, ask while, ask switch, and infer class methods. They produce a general parse error (NOLA1001) rather than a dedicated reserved-syntax diagnostic.

  • Node ≥ 22.18 is required to load .tsi alongside plain .ts files. The loader uses Node’s module hooks; running it directly with Bun or Deno is unsupported (NOLA3015). You can still use npm, pnpm, Yarn or Bun as your package manager, provided Node runs the program. See Node loader.
  • Server-side execution only. Importing .tsi into a client bundle fails with NOLA4001; running an ask in a browser raises NOLA3013. Put the import in a server entry point, route handler or server action.

The following are supported:

  • await inside an infer function — legal, for any ordinary promise.
  • Constructing an extractor at module level — legal and inert. Asking at module level — also legal: a top-level ask runs as its own <module> invocation (see ask).
  • Several contextual parameters on one function — legal; they compose into one block.
  • Calling one infer function from another with ask otherFn(…) — legal; that is how you compose them.

Next: nola.config.ts