Typed Forms Without Pain (Mapped Types + Generic Helpers)
A production-friendly pattern to type form values, errors, and validators using mapped types—no giant unions, no any.
On this page
What you’ll learn
- How mapped types model
values,errors, andtouchedconsistently - How to write typed validators that scale
- A pattern used across React/Next apps (framework-agnostic)
30‑second interview answer
Mapped types let you transform a form’s value type into related types like Errors<T> and Touched<T> while keeping keys in sync. This prevents bugs where you add a field but forget to update error handling. The key idea is: define the form data once, derive everything else from it.
Step 1: Define the form values type once
type SignupValues = {
email: string;
password: string;
marketingOptIn: boolean;
};Step 2: Derive related structures via mapped types
type Errors<T> = {
[K in keyof T]?: string;
};
type Touched<T> = {
[K in keyof T]?: boolean;
};
type SignupErrors = Errors<SignupValues>;
type SignupTouched = Touched<SignupValues>;This keeps keys aligned forever.
Step 3: Typed validators
A common validator shape:
type Validator<T> = (values: T) => Errors<T>;
const validateSignup: Validator<SignupValues> = (values) => {
const errors: Errors<SignupValues> = {};
if (!values.email.includes("@")) errors.email = "Invalid email";
if (values.password.length < 8) errors.password = "Min 8 characters";
return errors;
};No casts, no stringly-typed keys.
Step 4: Field-level validators with key-safe access
type FieldValidator<T, K extends keyof T> = (value: T[K], values: T) => string | undefined;
type FieldValidators<T> = {
[K in keyof T]?: FieldValidator<T, K>;
};
const fieldValidators: FieldValidators<SignupValues> = {
email: (email) => (email.includes("@") ? undefined : "Invalid email"),
password: (pw) => (pw.length >= 8 ? undefined : "Too short")
};Now the validator signature always matches the field type.
Common mistakes
- Storing errors as
Record<string, string>(loses key safety) - Copy-pasting field names into multiple types (guaranteed drift)
- Over-modeling nested forms before you need it
Production rule of thumb
- Define
Valuesonce. - Derive
Errors<T>,Touched<T>, validators, and field configs from it. - Prefer small, composable validators.
Interview questions
-
Q: What do mapped types buy you in forms?
- A: Key-level consistency: add/remove fields once and all derived types update.
-
Q: How do you type a validator for a specific field?
- A: Use generics like
FieldValidator<T, K>and map it across keys.
- A: Use generics like
Quick recap
- Mapped types keep form keys consistent.
- Typed validators scale without string keys.
- This is high-signal TypeScript that’s actually practical.
Looking for structured, offline interview prep?
Free online lessons • Portable Amazon Kindle / Paperback
Frontend Interview Guide (2025 Edition)
By Rajesh Dhiman
Comprehensive preparation covering React internals, Web Performance, CSS architecture, and system design questions.
JavaScript Interview Guide
By Rajesh Dhiman
Deep dive into the Event Loop, microtask draining, closures, prototypal inheritance, and asynchronous execution patterns.
Note: All lessons on Frontend Interview remain completely free to read online. As an Amazon Associate, we may earn from qualifying purchases.
Written by Rajesh Dhiman
Authored by Rajesh Dhiman and engineered at Eunix Tech. Focused on deep-dive frontend engineering, JavaScript runtime internals, React architecture, and web performance.