Skip to content

strict types · ecmascript-faithful · one source, every target

JavaScript, Perfected.

A strict, type-safe superset of JavaScript that follows the ECMAScript standard — sound types, null safety, exhaustive match, no any. Compiles to clean JS today; native binaries and WASM are on the roadmap.

$npm i -g @superjsorg/cli

Why Super.js

Correctness, by construction

Three beats: the problem with the status quo, what Super.js does about it, and what you get.

  1. 01The problem

    JavaScript lets bugs through. TypeScript leaks.

    null and undefined crash code at runtime, where users find them. TypeScript helps — until any quietly switches the checker off, casts paper over holes, and "impossible" states slip past the compiler into production.

    Cannot read properties of null is still the most common JS runtime error.

  2. 02The solution

    Strict types, faithful to ECMAScript.

    Super.js tracks the ECMAScript standard — every modern JS feature, ES5 through ES2025, type-checked. T? is the only nullable type. Sum types model data as named variants and match forces you to handle every one. any is banned; the escape hatch is spelled dynamic — explicit and greppable.

    A superset, not a fork — adopt it file by file, no rewrite.

  3. 03The payoff

    One source. Every target.

    Super.js compiles to clean, readable JavaScript today — no runtime library, no wrapper objects, no startup cost. The safety lives entirely in the compiler. And the same source is headed further: native binaries and WASM are on the roadmap, no language change required.

    Zero-overhead JS now; native & WASM backends next.

Features

Everything TypeScript should have been

Built from first principles. Every decision exists to make your code more correct.

🛡️

Null Safety

T? is the only nullable type. No null exceptions at runtime.

const x: string? = null
const y: string = x ?? "default"

Sum Types

Algebraic data types with exhaustive match — no impossible states.

type Result<T,E> = Ok(T) | Err(E)
const r: Result<number,string> = Ok(42)

Match Expressions

Exhaustive pattern matching. The compiler forces you to handle every case.

match r {
  Ok(v) => v * 2,
  Err(e) => 0
}

No any

any is banned. Use dynamic when you need an escape hatch — it's explicit.

// ❌  const x: any = fetch()
// ✅  const x: dynamic = fetch()

Gradual Typing

Mix typed and untyped code freely. Migrate at your own pace.

function greet(name) {  // untyped
  return "Hello, " + name
}
0

Zero Runtime

Compiles to plain JS. No runtime library, no overhead, ships anywhere.

// superjs build app.sjs
// plain JavaScript, no imports

Comparison

The same problem, solved correctly

Switch tabs — same program, three outcomes.

✅ The compiler forces you to handle it
// Super.js
function divide(a: number, b: number): Result<number, string> {
  if (b === 0) return Err("division by zero")
  return Ok(a / b)
}

match divide(10, 0) {
  Ok(v) => console.log(v),
  Err(e) => console.error(e)
}

Try it live

Edit the Super.js code on the left, hit Run, see compiled JavaScript on the right.

playground.sjs

Press Run to compile

Who it's for

Built for people who ship JavaScript

If any of these sound like you, Super.js was designed for your workflow.

🧹

TypeScript teams tired of any

You added strict mode and still ship "as any" to hit deadlines. Super.js removes the escape hatch by default — any is a compile error, and the holes that any hides simply close.

📦

Library authors

Your public API is a contract. Sum types and exhaustive match let you express it precisely, so callers cannot construct invalid states — and adding a variant tells you exactly which call sites must change.

🎯

Correctness-minded engineers

You reach for Rust’s Result, Option, and pattern matching, but ship to a JS runtime. Super.js brings those ideas to plain JavaScript — sound nullability and ADTs, zero runtime cost.

Quickstart

From zero to type-safe in 60 seconds

1

Install the compiler

npm install -g @superjsorg/cli
2

Write your first program

// hello.sjs
type Greeting = Formal(string) | Casual(string)

function greet(g: Greeting): string {
  return match g {
    Formal(name) => "Good day, " + name + ".",
    Casual(name) => "Hey " + name + "!"
  }
}

console.log(greet(Formal("World")))  // Good day, World.
console.log(greet(Casual("friend"))) // Hey friend!
3

Compile and run

superjs build hello.sjs
node dist/hello.js

Ecosystem

Works everywhere JavaScript does

🎨VS Code Extension
⚙️CLI Compiler
🛡️Type Checker
🔍Linter
Formatter
🟢Node.js
🌐Browser
🥟Bun
⚛️React
📦JSX / TSX
🎨VS Code Extension
⚙️CLI Compiler
🛡️Type Checker
🔍Linter
Formatter
🟢Node.js
🌐Browser
🥟Bun
⚛️React
📦JSX / TSX

Get Started

Start writing Super.js today.

Strict types, null-safe, ECMAScript-faithful. Zero config — compiles to clean JavaScript.

$npm i -g @superjsorg/cli