Non-null assertion (!)

The postfix ! asserts a value is not null or undefined. CruftScript backs the assertion with a real check: where it strips a nullable type it inserts a runtime test that faults if the value was actually nullish. It cannot rescue an unknown value, and a wholly-nullish target is a compile error.

The postfix ! asserts that a value is not null or undefined. CruftScript does not take that assertion on faith: where it strips a nullable type it also inserts a check that runs at runtime and faults if the value really was nullish.

expr!    // postfix; not the prefix logical-not !x, and not != or !==

The ! here is the postfix operator that follows an expression. It is distinct from the prefix logical-not in !x and from the != and !== comparison operators.

What it does over each kind of value

Over a nullable union, ! strips null and undefined from the type, and the lowering inserts a runtime non-null check that faults at the assertion site if the value is nullish. It is a checked narrowing, not a bare assertion.

const name: string | null = lookup()
return name!  // string, plus an inserted runtime check that faults if name is null

Note that ! must appear in an expression position such as a return — a bare name! written as its own statement is rejected in a runnable body today. Apply it where its value is used, as in the return above.

Over an already-non-nullish value there is nothing to strip, so ! is a no-op.

Over an unknown value it does not manufacture a type. The value stays unknown; ! cannot rescue it into something usable.

const v: unknown = getValue()
v!           // still unknown; ! does not invent a type

Over a wholly-nullish type with nothing left to keep, it is a compile error.

const x: null = null
x!           // error: nothing to narrow to

Why it works this way

TypeScript's x! erases to x with no runtime effect. It is one of that language's two named unsoundness hatches: you promise the value is present, the checker believes you, and nothing verifies the promise, so a wrong ! sails through to a failure elsewhere. CruftScript refuses that reading. Every accepted ! is one of three honest things: a proven no-op, a runtime-checked narrowing that catches a nullish value at the assertion site, or a rejected program. There is no unchecked ! that survives. When you genuinely want to remove nullishness, the sound routes are ordinary type narrowing or the NonNullable<T> utility type; ! is the one that pays for itself with a real check.

Limitations

  • The accepted strip runs code. Over a nullable union, ! is not free. It inserts a runtime check that can fault, which is the price of closing the soundness hole.
  • It cannot rescue unknown. ! over an unknown leaves it unknown. Narrow the value with a real check instead.
  • A wholly-nullish target is an error. If there is nothing non-nullish to keep, the assertion is rejected rather than silently allowed.