Hint
[K in keyof T] iterates over type keys — combine with as to remap keys, conditional types to filter, modifiers to change optionality
Mapped types transform existing types by iterating over their keys and applying transformations to each property.
// Basic structure
type Mapped<T> = {
[K in keyof T]: TransformedType;
};
// Value transformation — wrap each value in a Box
type Boxed<T> = {
[K in keyof T]: { value: T[K] };
};
type BoxedUser = Boxed<User>;
// { id: { value: number }; name: { value: string }; ... }
Key remapping with as:
// Add prefix to all keys
type Prefixed<T, P extends string> = {
[K in keyof T as `${P}_${string & K}`]: T[K];
};
type PrefixedUser = Prefixed<User, 'user'>;
// { user_id: number; user_name: string; ... }
// Convert to setters
type Setters<T> = {
[K in keyof T as `set${Capitalize<string & K>}`]: (value: T[K]) => void;
};
Filtering keys with conditional + never:
// Keep only method keys
type MethodKeys<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
// Keep only string-valued properties
type StringProps<T> = {
[K in keyof T as T[K] extends string ? K : never]: T[K];
};
// Flatten optional — convert T | undefined to T
type NonOptional<T> = {
[K in keyof T]-?: Exclude<T[K], undefined>;
};
[K in keyof T as CondType extends never ? never : K] is how TypeScript's built-in Omit and conditional key removal work. Mastering key remapping with as unlocks very powerful type transformations.