0Pricing
TypeScript Academy · Lesson

Compile-Time Input Validation

Reject malformed DSL expressions before runtime.

Compile-Time Input Validation is a free TypeScript Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Compile-Time Input Validation

Type-level DSLs can reject malformed expressions before runtime. Using template literal and conditional types, we validate the structure of a string at the type level and refuse invalid input.

Example: A Tiny Selector Language

Imagine accepting strings like "user.name" or "order.items.length". We want to reject "user." or ".name" at compile time.

Parsing With Template Literals

Template literal types split a string into parts using infer, the foundation of compile-time parsing. The real pattern is backtick-delimited (Head dot Tail with infer); we denote that split matcher as DotSplit.

// Real TS: backtick pattern matching Head, ".", Tail.

type Split<S extends string> =
  S extends DotSplit<infer Head, infer Tail>
    ? [Head, ...Split<Tail>]
    : [S];

type P = Split<"a.b.c">; // ["a", "b", "c"]

Validating Each Segment

A conditional type checks that no segment is empty. An empty segment marks the input invalid. The same DotSplit pattern (a backtick template literal in real code) drives the recursion.

type NonEmpty<S extends string> = S extends "" ? false : true;

type Valid<S extends string> =
  S extends DotSplit<infer H, infer T>
    ? H extends "" ? false : Valid<T>
    : NonEmpty<S>;

type V1 = Valid<"a.b">;  // true
type V2 = Valid<"a.">;   // false

Gating the API on Validity

Use the validity type to constrain a function parameter: valid strings keep their type; invalid ones resolve to never, so the call fails to compile.

declare function path<S extends string>(
  p: Valid<S> extends true ? S : never
): void;

path("user.name"); // ok
path("user.");     // Error: argument is never

Rejecting Unknown Tokens

You can restrict allowed characters too. Match only known segment patterns; anything else collapses to a rejecting type.

type Allowed = "user" | "order" | "name" | "items";
type CheckSeg<S extends string> = S extends Allowed ? true : false;

Validating Operators

For an expression DSL like "age > 18", match the operator with a template literal and ensure it is in an allowed set. The matcher (left space O space right) is a backtick template literal in real code; we denote it CondMatch.

type Op = ">" | "<" | "=" | ">=" | "<=";

// Real TS: backtick pattern -> left, " ", infer O, " ", right.
type IsCond<S extends string> =
  S extends CondMatch<infer O>
    ? O extends Op ? true : false
    : false;

type C1 = IsCond<"age > 18">; // true
type C2 = IsCond<"age ! 18">; // false

Combining Checks

Real validators intersect several conditions: non-empty segments, allowed tokens, balanced structure. Each is a conditional type; combine them with logical-style helper types.

type And<A, B> = A extends true ? (B extends true ? true : false) : false;

Recursion Limits

Type-level recursion has depth limits. For very long strings the compiler may error with "type instantiation is excessively deep". Keep parsed inputs bounded or simplify the grammar.

Better Than Runtime Parsing

A runtime parser only complains when the bad string is evaluated. Compile-time validation rejects the literal the moment you type it, with full editor feedback and zero runtime cost.

Why This Matters

Many DSLs accept string inputs (paths, queries, formats). Validating their structure in the type system catches typos and malformed expressions before the program runs, turning a class of runtime errors into compile errors.

Quick Check

Check your understanding of compile-time input validation.

Recap

You validated DSL input before runtime by parsing string literals with template literal types and infer, then checking segments and operators with conditional types. Gating a function parameter on the validity type makes malformed expressions resolve to never and fail to compile, with attention to recursion limits.

Frequently asked questions

Is the “Compile-Time Input Validation” lesson free?

Yes — the full text of “Compile-Time Input Validation” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.

What will I learn in “Compile-Time Input Validation”?

Reject malformed DSL expressions before runtime. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start TypeScript Academy?

No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Compile-Time Input Validation” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this TypeScript Academy lesson?

Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. What Is a Type-Level DSL
  2. Designing a Fluent Query DSL
  3. Compile-Time Input Validation
  4. Error Messages in Type-Level DSLs
← Back to TypeScript Academy