cd /news/developer-tools/a-stricter-typescript-for-a-world-wh… · home topics developer-tools article
[ARTICLE · art-83834] src=github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

A stricter TypeScript for a world where AI writes most of the code

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.

read6 min views9 publishedAug 2, 2026
A stricter TypeScript for a world where AI writes most of the code
Image: source

This is my proposal for TypeScript-Ultra-Strict: a stricter TypeScript for a world where AI writes most of the code.

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

Status: working MVP. packages/cli

implements tsus check

and tsus build

, packages/runtime

implements Option

/Result

/match

and the boundary layer, packages/plugin

provides webpack/Vite/esbuild/Bun adapters, and all 29 projects under examples/

pass (npm install && npm run examples

). LEARNINGS.md

documents what broke before the toolchain existed, how that shaped the design, and the known limitations.

TypeScript'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.

  • Removes null

andundefined

. In their place,Option<T>

andResult<T, E>

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

  • Removes var

. - Introduces an SDK for macros, used for pattern matching and variable destructuring over Option

,Result

, and tagged unions. (TC39 already has a pattern-matching proposal in the pipeline; this accelerates where the language is heading.)

Every existing DOM and npm API returns undefined

, throws, and hands you classes. Ultra-Strict code never sees those directly. At the boundary, a checked bindings layer converts T | undefined

and T | null

into Option<T>

, and throwing calls into Result<T, E>

. Inside the boundary, the strict rules hold everywhere.

Banning classes, nulls, and var

can be approximated with tsconfig and lint rules today. Two things need a real compiler:

  • 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.
  • The boundary layer, which needs type information to generate the Option

/Result

wrappers.

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

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

Any file with a .tsus

extension (TypeScript Ultra Strict) is processed under the strict rules and compiled to plain JavaScript. .ts

and .tsus

files coexist in one project, so adoption is per-file: an AI agent can write new modules in .tsus

while the legacy .ts

code keeps working untouched. Importing a .tsus

module from .ts

just works; importing .ts

(or any npm package) into .tsus

goes through the boundary layer, which rewrites the types so nullable returns arrive as Option<T>

and throwing functions arrive as Result<T, E>

.

What a .tsus

file looks like:

import { readFile } from "node:fs/promises"; // boundary-wrapped: returns Result

type User = { name: string; email: Option<string> };

const loadUser = async (path: string): Promise<Result<User, IoError>> => {
  const raw = await readFile(path, "utf8");
  return raw.map(parseUser);
};

// macro from the SDK
const greeting = match(user.email) {
  Some(email) => `Reach me at ${email}`,
  None => "No email on file",
};

packages/plugin

(@tsus/plugin) is one transform core with a thin adapter per host, all sharing the CLI's preprocessor and checker:

@tsus/plugin/webpack

: a . In Next.js, one rule innext.config.mjs

makes.tsus

importable from any page or component (examples/27-nextjs

, verified bynext build

emitting the rendered string into static HTML).@tsus/plugin/vite

: a Vite plugin, which also covers Astro, SvelteKit, and Nuxt through theirvite.plugins

config (examples/28-astro

).@tsus/plugin/esbuild

: an esbuild plugin. Bun's plugin API is esbuild-shaped, so the same object registers withBun.plugin

; with a one-linebunfig.toml

preload,bun run

executes.tsus

imports natively with no build step (examples/29-bun

).

The adapters deliberately leave import specifiers untouched: the host bundler resolves .tsus

to .tsus

chains through its own pipeline and each hop hits the transform again. The tsus

CLI stays the standalone path (and the CI path, via tsus check --json

).

Tooling:

tsus build

compiles to JS,tsus check

type-checks without emitting. Both run as an esbuild/swc plugin so existing bundler setups pick up.tsus

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

  • Diagnostics are machine-first: every error has a stable code, a JSON output mode, and a suggested fix, so an agent can consume tsus check --json

in 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 .tsus

packages ship compiled JS plus.d.ts

files, so consumers don't need to know the source language existed.

examples/

is the test suite: 29 small projects, each with an example.json

declaring what must happen. npm run examples

builds and executes all of them and fails on any drift.

Core language and runtime

Example Shows
01-hello
Smallest possible .tsus file compiling to plain ESM
02-option-basics
Option<T> with map /andThen /unwrapOr
03-result-basics
Result<T, E> with map /mapErr
04-match-option , 05-match-result
The match macro over Some/None and Ok/Err
06-tagged-union
User-defined tagged unions with a _ wildcard arm

Rejected on purpose (these pass by failing the checker with the right code)

Example Code
07-banned-null
TSUS002
08-banned-class
TSUS001
09-banned-var
TSUS004
10-banned-undefined
TSUS003
11-banned-throw
TSUS005

Interop and stress

Example Shows
12-tsus-imports-tsus , 20-deep-chain
.tsus import chains, four levels deep
13-tsus-imports-ts , 14-ts-imports-tsus
Mixed projects in both directions; .ts keeps its classes and nulls
15-npm-dependency
zod feeding Result
16-boundary-fs , 26-json-boundary
wrapAsync /wrapSync turning throws into Result
17-nested-match , 18-generics , 19-async-result
Nested matches, generic signatures, await inside match arms
21-circular-imports
Function-level .tsus cycles (fine, because ESM)
22-mixed-project
ts + tsus + zod + boundary in one project
24-hostile-syntax
Decoy match blocks in strings, comments, and template literals
25-shadowed-match
A user function named match staying a plain call

Runtimes and frameworks

Example Shows
23-cloudflare-worker
Cloudflare { fetch } module shape, tested against real Request /Response
27-nextjs
Next.js 14 via the webpack ; next build renders .tsus output into static HTML
28-astro
Astro 4 via the Vite plugin, verified in built HTML
29-bun
Bun runs .tsus imports natively via a bunfig.toml preload, no build step
── more in #developer-tools 4 stories · sorted by recency
── more on @typescript-ultra-strict 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/a-stricter-typescrip…] indexed:0 read:6min 2026-08-02 ·