{"slug": "a-stricter-typescript-for-a-world-where-ai-writes-most-of-the-code", "title": "A stricter TypeScript for a world where AI writes most of the code", "summary": "A developer proposes TypeScript-Ultra-Strict, a stricter TypeScript variant that removes null, undefined, classes, and var, replacing them with Option<T> and Result<T, E> types, and introduces a macro SDK for pattern matching, targeting a world where AI writes most code. The working MVP includes a CLI, runtime, plugin adapters for webpack/Vite/esbuild/Bun, and 29 example projects, with per-file adoption via .tsus extensions. The proposal argues that AI-generated code can afford stricter, more declarative and verifiable language features, similar to Rust, while leveraging the existing TypeScript ecosystem and JavaScript runtime.", "body_md": "This is my proposal for TypeScript-Ultra-Strict: a stricter TypeScript for a world where AI writes most of the code.\n\nThis repo is a thought experiment, not a production tool.The compiler works and every example passes, but there is no semantic type-checking, no exhaustiveness checking, no published packages, and no stability promise. It exists to make the proposal concrete enough to argue with. Do not build anything you care about on it yet.\n\n**Status:** working MVP. `packages/cli`\n\nimplements `tsus check`\n\nand `tsus build`\n\n, `packages/runtime`\n\nimplements `Option`\n\n/`Result`\n\n/`match`\n\nand the boundary layer, `packages/plugin`\n\nprovides webpack/Vite/esbuild/Bun adapters, and all 29 projects under `examples/`\n\npass (`npm install && npm run examples`\n\n). `LEARNINGS.md`\n\ndocuments what broke before the toolchain existed, how that shaped the design, and the known limitations.\n\nTypeScript's early design decisions assumed humans would write and maintain it, so a lot of features exist to make a human's life easier. We valued speed over quality. With AI writing most of our code, we can flip that tradeoff and force the language to be declarative and verifiable, like Rust.\n\n- Removes\n`null`\n\nand`undefined`\n\n. In their place,`Option<T>`\n\nand`Result<T, E>`\n\nbecome first-class types. This is the centerpiece: the removals below only work because these replacements exist. - Removes classes. Data is plain objects; behavior lives in functions.\n- Removes\n`var`\n\n. - Introduces an SDK for macros, used for pattern matching and variable destructuring over\n`Option`\n\n,`Result`\n\n, and tagged unions. (TC39 already has a pattern-matching proposal in the pipeline; this accelerates where the language is heading.)\n\nEvery existing DOM and npm API returns `undefined`\n\n, throws, and hands you classes. Ultra-Strict code never sees those directly. At the boundary, a checked bindings layer converts `T | undefined`\n\nand `T | null`\n\ninto `Option<T>`\n\n, and throwing calls into `Result<T, E>`\n\n. Inside the boundary, the strict rules hold everywhere.\n\nBanning classes, nulls, and `var`\n\ncan be approximated with tsconfig and lint rules today. Two things need a real compiler:\n\n- The macro SDK. This is the honest cost of the proposal: TypeScript's types are fully erasable, which is why esbuild and swc can strip them in a single fast pass. Macros break that property. The bet is that with AI writing the code, we should spend build-time budget on expressiveness and checkability rather than on keeping type-stripping trivial.\n- The boundary layer, which needs type information to generate the\n`Option`\n\n/`Result`\n\nwrappers.\n\nBack in 2008, Google shipped Chrome and V8, and the industry built its edge compute on top of that runtime. Cloudflare Workers runs V8 isolates directly. Node, Deno, and Bun's ecosystem all trace back to it. JavaScript and ESM are the substrate that's already deployed everywhere.\n\nTypeScript is the typed layer the ecosystem already adopted. Rather than asking everyone to move to a new language, Ultra-Strict is a subset-plus-macros of a language AI models already know deeply, targeting a runtime that's already everywhere.\n\nAny file with a `.tsus`\n\nextension (TypeScript Ultra Strict) is processed under the strict rules and compiled to plain JavaScript. `.ts`\n\nand `.tsus`\n\nfiles coexist in one project, so adoption is per-file: an AI agent can write new modules in `.tsus`\n\nwhile the legacy `.ts`\n\ncode keeps working untouched. Importing a `.tsus`\n\nmodule from `.ts`\n\njust works; importing `.ts`\n\n(or any npm package) into `.tsus`\n\ngoes through the boundary layer, which rewrites the types so nullable returns arrive as `Option<T>`\n\nand throwing functions arrive as `Result<T, E>`\n\n.\n\nWhat a `.tsus`\n\nfile looks like:\n\n``` js\nimport { readFile } from \"node:fs/promises\"; // boundary-wrapped: returns Result\n\ntype User = { name: string; email: Option<string> };\n\nconst loadUser = async (path: string): Promise<Result<User, IoError>> => {\n  const raw = await readFile(path, \"utf8\");\n  return raw.map(parseUser);\n};\n\n// macro from the SDK\nconst greeting = match(user.email) {\n  Some(email) => `Reach me at ${email}`,\n  None => \"No email on file\",\n};\n```\n\n`packages/plugin`\n\n(@tsus/plugin) is one transform core with a thin adapter per host, all sharing the CLI's preprocessor and checker:\n\n`@tsus/plugin/webpack`\n\n: a loader. In Next.js, one rule in`next.config.mjs`\n\nmakes`.tsus`\n\nimportable from any page or component (`examples/27-nextjs`\n\n, verified by`next build`\n\nemitting the rendered string into static HTML).`@tsus/plugin/vite`\n\n: a Vite plugin, which also covers Astro, SvelteKit, and Nuxt through their`vite.plugins`\n\nconfig (`examples/28-astro`\n\n).`@tsus/plugin/esbuild`\n\n: an esbuild plugin. Bun's plugin API is esbuild-shaped, so the same object registers with`Bun.plugin`\n\n; with a one-line`bunfig.toml`\n\npreload,`bun run`\n\nexecutes`.tsus`\n\nimports natively with no build step (`examples/29-bun`\n\n).\n\nThe adapters deliberately leave import specifiers untouched: the host bundler resolves `.tsus`\n\nto `.tsus`\n\nchains through its own pipeline and each hop hits the transform again. The `tsus`\n\nCLI stays the standalone path (and the CI path, via `tsus check --json`\n\n).\n\nTooling:\n\n`tsus build`\n\ncompiles to JS,`tsus check`\n\ntype-checks without emitting. Both run as an esbuild/swc plugin so existing bundler setups pick up`.tsus`\n\nfiles without config changes.- Editor support ships as a TypeScript language service plugin, so VS Code and every TS-aware editor get diagnostics, go-to-definition, and macro expansion previews for free.\n- Diagnostics are machine-first: every error has a stable code, a JSON output mode, and a suggested fix, so an agent can consume\n`tsus check --json`\n\nin a loop without parsing prose. Human-readable output is a rendering of the same data. - No new package manager and no new registry. npm packages work through the boundary layer, and published\n`.tsus`\n\npackages ship compiled JS plus`.d.ts`\n\nfiles, so consumers don't need to know the source language existed.\n\n`examples/`\n\nis the test suite: 29 small projects, each with an `example.json`\n\ndeclaring what must happen. `npm run examples`\n\nbuilds and executes all of them and fails on any drift.\n\n**Core language and runtime**\n\n| Example | Shows |\n|---|---|\n`01-hello` |\nSmallest possible `.tsus` file compiling to plain ESM |\n`02-option-basics` |\n`Option<T>` with `map` /`andThen` /`unwrapOr` |\n`03-result-basics` |\n`Result<T, E>` with `map` /`mapErr` |\n`04-match-option` , `05-match-result` |\nThe `match` macro over Some/None and Ok/Err |\n`06-tagged-union` |\nUser-defined tagged unions with a `_` wildcard arm |\n\n**Rejected on purpose** (these pass by failing the checker with the right code)\n\n| Example | Code |\n|---|---|\n`07-banned-null` |\nTSUS002 |\n`08-banned-class` |\nTSUS001 |\n`09-banned-var` |\nTSUS004 |\n`10-banned-undefined` |\nTSUS003 |\n`11-banned-throw` |\nTSUS005 |\n\n**Interop and stress**\n\n| Example | Shows |\n|---|---|\n`12-tsus-imports-tsus` , `20-deep-chain` |\n`.tsus` import chains, four levels deep |\n`13-tsus-imports-ts` , `14-ts-imports-tsus` |\nMixed projects in both directions; `.ts` keeps its classes and nulls |\n`15-npm-dependency` |\nzod feeding `Result` |\n`16-boundary-fs` , `26-json-boundary` |\n`wrapAsync` /`wrapSync` turning throws into `Result` |\n`17-nested-match` , `18-generics` , `19-async-result` |\nNested matches, generic signatures, `await` inside match arms |\n`21-circular-imports` |\nFunction-level `.tsus` cycles (fine, because ESM) |\n`22-mixed-project` |\nts + tsus + zod + boundary in one project |\n`24-hostile-syntax` |\nDecoy `match` blocks in strings, comments, and template literals |\n`25-shadowed-match` |\nA user function named `match` staying a plain call |\n\n**Runtimes and frameworks**\n\n| Example | Shows |\n|---|---|\n`23-cloudflare-worker` |\nCloudflare `{ fetch }` module shape, tested against real `Request` /`Response` |\n`27-nextjs` |\nNext.js 14 via the webpack loader; `next build` renders `.tsus` output into static HTML |\n`28-astro` |\nAstro 4 via the Vite plugin, verified in built HTML |\n`29-bun` |\nBun runs `.tsus` imports natively via a `bunfig.toml` preload, no build step |", "url": "https://wpnews.pro/news/a-stricter-typescript-for-a-world-where-ai-writes-most-of-the-code", "canonical_source": "https://github.com/chitalian/Typescript-Ultra-Strict", "published_at": "2026-08-02 17:30:15+00:00", "updated_at": "2026-08-02 17:52:51.410043+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence"], "entities": ["TypeScript-Ultra-Strict", "TypeScript", "Google", "Chrome", "V8", "Cloudflare Workers", "Node", "Deno"], "alternates": {"html": "https://wpnews.pro/news/a-stricter-typescript-for-a-world-where-ai-writes-most-of-the-code", "markdown": "https://wpnews.pro/news/a-stricter-typescript-for-a-world-where-ai-writes-most-of-the-code.md", "text": "https://wpnews.pro/news/a-stricter-typescript-for-a-world-where-ai-writes-most-of-the-code.txt", "jsonld": "https://wpnews.pro/news/a-stricter-typescript-for-a-world-where-ai-writes-most-of-the-code.jsonld"}}