CruftScript type system
The overview and directory of CruftScript's static type system: the shared rules every construct obeys (no any, unknown must be checked before use, an undecidable answer is an error) and links to one page per type construct, from primitives through generics and conditional types.
CruftScript has a static type system: you annotate your code with types, and the compiler checks them before the program runs. The shape of it will be familiar if you have used TypeScript, because the syntax is close on purpose. What is different is the stance: where TypeScript will, in a few well-known places, take your word for something it cannot prove, CruftScript refuses. A type in CruftScript is a promise the compiler actually keeps.
This section is one page per construct. Start here for the ideas that run through all of them, then follow the directory below to the piece you need.
The rules they all obey
A handful of principles are shared by every construct, so they are worth stating once up front.
- There is no
any. TypeScript'sanyis a value the checker stops reasoning about. CruftScript has no such keyword.unknownis the only catch-all, and it must be checked before use. unknownis a value you have to check. Anything can be stored asunknown, but you cannot use it until a real runtime check tells you what it is. There is no cast or assertion that skips that check.- When the compiler cannot decide, it stops. If a type computation has no provable answer, the compiler reports an error instead of guessing. This is the most common way CruftScript differs from TypeScript, which tends to fall back to a broad type and continue.
- The defaults are the safe ones. Container types are compared strictly, recursive type computations must be shown to finish, and the unsafe escape hatches TypeScript offers (
!,as unknown as T) are either removed or turned into checks that actually run.
A practical note: the type checker is broad and works today, but the subset of CruftScript that runs directly is narrow, so most programs that use these annotations run through the ordinary compile-and-strip path. Each page says plainly where a construct is fully working and where it is designed but not yet accepted.
The types
Foundations
- Primitive types —
string,number,boolean, and the rest, compared by name. - The
unknowntype — the one catch-all, and why you must check it before use. - The
nevertype — the empty type, and how it signals an impossible or fully-handled case.
Values as types
- Literal types — exact values as types, and
as const. - Template literal types — building string types by interpolation.
Composite types
- Object types — structural records, matched by shape.
- Tuple types — fixed-length, position-typed sequences.
- Array types —
T[]andArray<T>, checked element by element.
Combining types
- Union types — a value that is one of several types.
- Intersection types — the all-of combinator, and its current limits.
Narrowing
- Type narrowing — the runtime checks that refine a value's type in a branch.
- Type predicates — your own narrowing functions, and why their bodies are not taken on faith.
Generics
- Generics — type parameters, constraints, and inference.
- Variance annotations —
inandout, and why the default is invariance.
Type-level computation
- Conditional types — branching at the type level.
infer— capturing a piece of a type inside a condition.- Recursive conditional types — self-referential types that must be shown to finish.
- Mapped types — computing a type per key.
keyof— the keys of a type as a union.- The
typeoftype query — the static type of a value. - Indexed access types — looking up a value type by key.
Inference and assertions
- Type inference — how the compiler fills in types, and why failure is an error.
satisfies— checking a value against a type without widening it.- Type assertions (
as) — casts, limited to ones that can be proven or checked. - Non-null assertion (
!) — a checked strip ofnullandundefined, not a free pass.
Runtime-bearing constructs
- Decorators — the intended sound subset, and its current status.
- Concurrency and capability types — the type-level face of the compartment and shared-memory model.