Run-time validation — checking data where it enters the program¶
Level: 201 · for anyone who reads data from outside the program
Stub — an outline, not a lesson. There is no runnable example behind this page yet, so nothing on it has been through the check that backs every other claim in this library. The questions below are what the finished page has to answer.
One line: Types are gone at run time, so the check has to be code: a parseOrder(data: unknown): Order that tests each field with typeof and in satisfies tsc and turns {"total": "99"} into a TypeError at the border instead of a wrong 991 later.
Keywords: runtime validation, schema validation
What the finished page will answer¶
- What must
parseOrder(data: unknown): Ordertest before tsc accepts its return value? - Why does
return datafail after every check has passed, whilereturn { id: data.id, total: data.total }succeeds? - What does the validator do with
{"id": 1, "total": "99"}, and where in the program does the failure now appear? - What happens when a type predicate
isOrder(x): x is Orderhas a bug in its body — does tsc notice? - How can the
Ordertype be taken from the validator withReturnType<typeof parseOrder>, so the two cannot drift apart?
Examples it will need¶
-
runtime_validation_parse_order_sh.sh— tsc's silence, 100 for a valid order, and the TypeError the validator throws for a string total -
runtime_validation_return_data_tserror.ts— the TS2322 error for returning the narrowed object itself, whose properties are still unknown -
runtime_validation_wrong_predicate_ts.ts— a type predicate with a bug, the bad value it lets through, and the wrong sum that follows
See also¶
- External data — where unchecked data comes from
- Type predicates — x is T, which tsc trusts without checking
- Narrowing — the typeof and in checks a validator is built from
- Type assertions — the assertion a validator replaces
- Encodings: Validation is a boundary ↗ — the UTF-8 version: check at the door, and let the type remember
- Rust: Validating at the boundary ↗ — the same rule at Rust's C boundary: validate first, then trust
- Regex: Validating input ↗ — checking a string field's format, the regex part of validation