TypeScript Type Safety
Project workbook · Path 77

Create a typed parser for an unknown registration payload and represent success and failure with a discriminated union.

The case

A fictional registration endpoint receives unknown JSON values. A valid payload has a nonblank string name and an integer seats value from 1 to 4. Type assertions alone cannot validate incoming runtime data. The local exercise sends nothing to a server.

PayloadExpected result
{"name":"Ada","seats":2}valid
{"name":"Ben","seats":"2"}invalid: string seats
{"name":"","seats":1}invalid: blank name
nullinvalid: not object
STAGE 1

Distinguish static and runtime checks

TypeScript can detect inconsistencies in typed code, but external input still arrives at runtime. Treat parsed JSON as unknown and validate the properties you need. Do not use any to silence a boundary problem. This case is deliberately small so the relationship between checks and returned types is visible.

Your task

Define Registration and ParseResult without using any.

Required output

Type definitions

Record your result and evidence here or in a separate file.

Review gate

Success and failure branches have different explicit discriminants.

If the gate is not met

Replace an unchecked cast with a runtime condition.

STAGE 2

Narrow the input safely

Check for a non-null object before accessing properties. Then validate each property’s type and allowed range. Arrays are objects too, so explicitly reject them for this contract. Return a structured error instead of throwing for routine invalid input, and avoid including sensitive raw payloads in messages.

Your task

Implement parseRegistration(value: unknown).

Required output

Boundary parser

Record your result and evidence here or in a separate file.

Review gate

All four supplied cases return the expected branch without crashing.

If the gate is not met

Test null and arrays before property access.

STAGE 3

Use the result exhaustively

A discriminated union lets callers use validated data only in the success branch. A reusable result type can express the same pattern across parsers without weakening the boundary. Keep generics focused on a real repeated relationship; extra abstraction is not automatically safer or clearer.

Your task

Write a consumer that formats valid seats and displays an error otherwise.

Required output

Typed consumer

Record your result and evidence here or in a separate file.

Review gate

The compiler rejects access to data in the failure branch.

If the gate is not met

Narrow on the discriminant before reading branch-specific fields.

STAGE 4

Test boundaries and compilation

Compiler checks and runtime tests answer different questions. Run strict compilation and execute cases for zero, one, four, five, fractional seats, arrays and null. Record the actual toolchain used. A passing compiler alone does not prove that malformed JSON is refused.

Your task

Run the supplied checks and add a missing-property case.

Required output

Compile and runtime evidence

Record your result and evidence here or in a separate file.

Review gate

Boundary values 1 and 4 pass; out-of-range and non-integer values fail.

If the gate is not met

Name the expected runtime result separately from the expected compiler result.

STAGE 5

Document the contract

A parser contract should explain normalization, ignored properties and error behavior. This case trims the name and accepts only the two validated fields in the returned value. Extra input properties are ignored rather than copied. State that this is validation for a local example, not complete API security.

Your task

Write the input contract and an example caller.

Required output

Parser handoff

Record your result and evidence here or in a separate file.

Review gate

The returned object does not blindly spread unknown input fields.

If the gate is not met

Construct the validated output explicitly.

Final project

Deliver types, parser, consumer, strict compiler settings, runtime cases and README. Include one intentionally invalid caller in a separate compile-fail example and explain the error.

Critical condition

No unchecked assertion or any bypasses the external-data boundary.

CriterionPointsEvidence
Evidence and correctness30Calculations, source use and results match the supplied case; limitations are honest.
Required artifacts30All five stage outputs and the capstone handoff are present and inspectable.
Reasoning and decisions20Choices, assumptions, alternatives and the case-specific critical condition are explained.
Reproducibility10A reviewer can follow the stated steps and distinguish expected from observed results.
Clear communication10Labels, units, structure and evidence references make the work easy to review.

Score at least 80/100, supply every required artifact, and satisfy the path-specific critical condition. Rework missing evidence before marking complete.

Worked reference

The string "2" is rejected rather than coerced. A valid input {name:" Ada ", seats:2} becomes {name:"Ada", seats:2}. null and arrays fail the object contract. A success result exposes data; a failure exposes an error and no data field.

Boundaries

This is a local type-and-validation exercise, not authentication, authorization or a deployed API.