Skip to content

Language

ChadScript is a statically-typed subset of TypeScript that compiles to native code. You write standard TypeScript — variables, functions, classes, interfaces, async/await, modules — and the compiler handles the rest.

Can I parse JSON? Yes. JSON.parse<T>() and JSON.stringify() are built in — define an interface for your data shape, and the compiler handles the rest. See cjq — a jq clone written in ChadScript.

Can I query a database? Yes. SQLite is built in — sqlite.open(), sqlite.query(), parameterized queries, transactions. See cql — run SQL on CSV files, compiled to a native binary.

Can I build an HTTP server? Yes. Router, httpServe, WebSocket — all built in. See it live at chadsmith.dev/hn.

The full Standard Library covers HTTP, SQLite, fetch, crypto, JSON, filesystem, and more — no packages to install.

The constraint is that all types must be resolved at compile time: no any, no eval, no runtime type inspection. Closures capture by value. The tables below describe the full feature set.

Core Language

FeatureStatus
let, const, varSupported
if/else if/else, for, for...of, while, do...while, switchSupported
break, continue, returnSupported
try/catch/finally, throwSupported
Template literals (`hello ${name}`)Supported
Destructuring (arrays and objects)Supported
Spread operator (...)Supported
Ternary (? :), nullish coalescing (??)Supported
Type assertions (as Type)Supported
typeofSupported (resolved at compile time)
All arithmetic, comparison, logical, bitwise operatorsSupported
Pre/post increment/decrement (++, --)Supported
Compound assignment (+=, -=, *=, /=, |=, &=)Supported
Regular expressions (/pattern/flags)Supported
for...inSupported (desugared to for...of Object.keys())
Computed property access (obj[key])Supported (read and write, for objects with known fields)
Generator functions (function*, yield)Not supported
DecoratorsNot supported
Tagged template literalsNot supported
Labeled statementsNot supported
with statementNot supported
Comma operatorNot supported

Functions

FeatureStatus
Named functionsSupported
Arrow functionsSupported
async/awaitSupported
Default parametersSupported
Rest parameters (...args)Supported
ClosuresSupported (capture by value; post-capture mutation is a compile error)
declare function (FFI)Supported (see FFI)
Async generators / for await...ofNot supported

Types and Data Structures

FeatureStatus
number, string, boolean, null, undefinedSupported
number[], string[] (typed arrays)Supported
Uint8ArraySupported
Object literals / interfaces / type aliases (fixed-layout structs)Supported
Map<K, V>, Set<T>Supported
Enums (numeric and string)Supported
Type aliasesSupported
Union types (string | null)Supported (nullable unions only)
any, unknown, neverNot supported
User-defined generics (<T>)Partial — generic classes and functions supported; numeric type params not supported
Intersection types (A & B)Not supported
Mapped / conditional / template literal typesNot supported
satisfies, instanceof, SymbolNot supported
WeakMap, WeakSet, WeakRefNot supported
SharedArrayBuffer, AtomicsNot supported
FinalizationRegistry, IntlNot supported

Classes & Interfaces

Classes, interfaces, and type aliases work like standard TypeScript with a few differences. type Foo = { ... } and interface Foo { ... } are interchangeable for defining object shapes.

Key differences from TypeScript:

  • No instanceof — there are no runtime type tags
  • Static dispatch — method calls are resolved at compile time, not dynamically
  • Interfaces/types are data-only — they define fields, not methods. To attach methods to a type, use a class.
  • Access modifiers not enforced at runtimeprivate/protected are parsed but all fields are accessible in the compiled output. Run chad init to get TypeScript type-checking in your editor, which will flag access violations before you compile.
FeatureStatus
Properties (typed fields)Supported
ConstructorsSupported
Parameter properties (constructor(private name: string))Supported
Instance methodsSupported
Getters / settersNot supported
extends (single inheritance)Supported
implementsSupported
Interface inheritance (extends)Supported
Static methods and fieldsSupported
Abstract classesNot yet supported
Private class fields (#field)Not supported
DecoratorsNot supported

Field ordering — object literals are automatically reordered to match the declared field order. You can write fields in any order:

typescript
type Person = {
  name: string;
  age: number;
  city: string;
};

const p: Person = { age: 30, city: "NYC", name: "Alice" }; // works fine

Generics

Generic classes and functions are supported with reference type parameters (strings, interfaces, classes). Numeric type params (number) are not supported.

typescript
class Stack<T> {
  items: T[];
  constructor() { this.items = []; }
  push(x: T): void { this.items.push(x); }
  pop(): T { return this.items.pop(); }
  size(): number { return this.items.length; }
}

const s = new Stack<string>();
s.push("hello");
console.log(s.pop()); // "hello"
typescript
function identity<T>(x: T): T { return x; }
function first<T>(arr: T[]): T { return arr[0]; }

const val = identity<string>("hi");

Multi-parameter generics (Pair<A, B>) and generic classes with interface type params also work.

Modules

FeatureStatus
import { foo } from './bar'Supported
import * as bar from './bar'Supported
import { foo as baz } from './bar'Supported
Default importsSupported
Named exportsSupported
Re-exports (export { foo } from './bar')Supported
export defaultSupported
Dynamic import()Not supported

Async

FeatureStatus
async/awaitSupported
Promise.all, Promise.race, Promise.allSettled, Promise.anySupported
Promise.resolve, Promise.rejectSupported
.then(), .catch(), .finally()Supported
setTimeout, setInterval, clearTimeout, clearIntervalSupported

JSX

FeatureStatus
JSX elements (<Tag prop={v} />)Supported (desugared to createElement() calls)
Fragments (<>...</>)Supported
Expression attributes (prop={expr})Supported
String attributes (prop="text")Supported
Self-closing elements (<Tag />)Supported
Nested elementsSupported

JSX is desugared at parse time into createElement(tag, props, children) calls. You provide the createElement function — ChadScript doesn't ship a framework. Files must use .tsx extension.

Dynamic Features

These require runtime code evaluation and are not possible in a native compiler:

FeatureStatus
eval()Not supported
Function() constructorNot supported
Proxy / ReflectNot supported
globalThisNot supported

Numbers

All numbers are number (no separate integer type). Integer literal expressions use native 64-bit integer instructions — 42 + 10 compiles to add i64 rather than fadd double. Division always returns a float. Variables are stored as doubles.

Strings

Strings are null-terminated C strings, not JavaScript's UTF-16 strings. They work fine for ASCII and UTF-8 text but cannot contain embedded null bytes.

Closures

Arrow functions and nested functions can capture outer variables. Captures are by value — the closure gets a snapshot of the variable at the point of capture. Mutating a variable after a closure captures it is a compile error, preventing an entire class of bugs where closures silently observe stale or unexpected state:

typescript
let x = 1;
const f = () => console.log(x);
x = 2; // error: variable 'x' is reassigned after being captured by a closure

This is a deliberate design choice. If you need shared mutable state, use an object:

typescript
const state = { count: 0 };
const inc = () => { state.count += 1; };
inc();
console.log(state.count); // 1

Inline lambdas with captures work in array methods:

typescript
const offset = 10;
const result = [1, 2, 3].map(x => x + offset); // [11, 12, 13]