Introduction
Nudo is a type inference engine for JavaScript. The type system is Abs (shape × term × pred × conf): types are computable values whose constraints participate in algebra (x>0 ⇒ x+1>1). Production analysis is Abs-native — there is no second IR. TypeScript sources are also accepted: type annotations are stripped and the code is inferred with plain JS semantics.
How It Works
Nudo executes your code under abstract interpretation (B-path transpile+exec, with an ast-eval fallback). Call-site facts drive evaluation; optional @nudo:case witnesses are debug / nudo test only; the engine produces Abs results, rendered extensionally for display (formatShape) and projected one-way to .d.ts / zod when needed.
Obligations — what nudo check enforces — come only from explicit contracts:
- sidecar templates in
*.nudo.js(constraint builders such asnumber().gt(0),shape({...}),fn({...}, …)) - in-source
@nudo:refine/@nudo:interface(same grammar; sidecar is the main product path)
No contract and no call-site evidence → any / honest unknown. Nudo does not invent required fields from body AST scans.
Nudo vs TypeScript
| TypeScript | Nudo |
|---|---|
| Declare types up front; compiler checks usage | Write plain JavaScript; engine infers Abs by executing it |
Requires .ts files or JSDoc annotations | Sidecar contracts (*.nudo.js / @nudo:refine / @nudo:interface) optional; @nudo:case is debug-only |
| Types describe intent | Inferred Abs describes observed behavior; contracts describe obligations |
Example: call site + a sidecar contract
// process.js
export function process(x) {
return x * 2;
}
process(5);
// process.nudo.js — obligation (check gate)
import { number, fn } from "@nudojs/core";
export const process = fn({ x: number().gt(0) }, number());
nudo infer reports the observed call site (call@L5: (5) => 10). nudo check enforces the sidecar: process(0) fails with nudo:constraint-violated (actual ⊭ expected). Optional @nudo:case witnesses (constraint builders such as number()) are debug / nudo test only — not the contract product; analysis always runs on Abs.
Beyond TypeScript
Nudo can compute types that TypeScript’s type system cannot express:
// String concatenation preserves structure
"0x" + string // → `0x${string}` (TS: string)
// Literal string methods compute precisely
"hello".toUpperCase() // → "HELLO" (TS: string)
"hello".slice(1, 3) // → "el" (TS: string)
"a,b,c".split(",") // → ["a", "b", "c"] (TS: string[])
// Loops evaluate on Abs
let sum = 0;
for (let i = 0; i < 5; i++) sum += i;
// sum → 10 (TS: number)
The same algebra powers nudo check — a refinement gate on Abs. Reports use actual ⊭ expected, not TypeScript diagnostic prose. TypeScript .d.ts emit is an ecosystem compatibility channel, not the primary type model.
What's Next
- Installation — Install the CLI, VS Code extension, and Vite plugin
- Quick Start — Run
nudo inferon your first file - Concept Layers — Day-0 / Day-1 sidecars / advanced Abs
- Nudo vs TypeScript — Where replacement is real, where TS stays, coexistence
- Coexistence — Monorepo recipes (JS=Nudo, TS=tsc)
- Type Values (Abs) — shape × term × pred × conf
- Call-Site Discovery — Let Nudo mine your tests for real call shapes
- nudo check — Refinement gate on Abs
- Language Semantics — What Nudo models precisely, and what still degrades to
unknown