← All Posts / TypeScriptJune 2026 / 7 min read / 310 words
TypeScript for Real Projects: The Types You Will Actually Use

TypeScript for Real Projects: The Types You Will Actually Use

Most TypeScript content online is either a basic syntax tour or an advanced type-theory exercise. The features that actually pay rent in product code sit in between: a small set of patterns that catch real bugs without turning the codebase into a puzzle.

TL;DR / Written for skimmers

A type with five optional fields usually models five different states badly. A discriminated union with a status field and only the fields relevant to that status models the same data accurately, and the compiler can narrow it for you in every branch. Pick and Omit let a type reuse another type's shape instead of redeclaring fields by hand, which keeps a form type and its source type from drifting apart as the project evolves. Casting a value with as silences the compiler. The satisfies operator checks the value against a type without changing its inferred type, so you keep the precise literal type while still getting an error if something does not match the shape you expected. Strict typing pays off at the boundaries of a system: API responses, form inputs, environment variables. Forcing the same rigor onto every internal helper function often costs more time than it saves.

Discriminated unions instead of optional-field soup

A type with five optional fields usually models five different states badly. A discriminated union with a status field and only the fields relevant to that status models the same data accurately, and the compiler can narrow it for you in every branch.

This pattern shows up constantly in API responses and async state: loading, success and error are different shapes, not one shape with everything marked optional.

Pick, Omit and the utility types worth memorizing

Pick and Omit let a type reuse another type's shape instead of redeclaring fields by hand, which keeps a form type and its source type from drifting apart as the project evolves.

Partial and Required round out the set that gets used daily: Partial for update payloads where every field is optional, Required for the rare case where you need to guarantee everything is present.

The satisfies operator and why it is better than casting

Casting a value with as silences the compiler. The satisfies operator checks the value against a type without changing its inferred type, so you keep the precise literal type while still getting an error if something does not match the shape you expected.

That combination, accurate inference plus a real check, is what makes satisfies a better default than as for object literals like configuration values or route definitions.

Where strict types should stop

Strict typing pays off at the boundaries of a system: API responses, form inputs, environment variables. Forcing the same rigor onto every internal helper function often costs more time than it saves.

A practical rule is to type the edges precisely and let inference handle the middle. That keeps the type system working for the team instead of becoming a second programming language to maintain.

← All Posts
TypeScriptTypesJavaScript