Key Remapping with as
Rename or filter keys inside a mapped type — reshape objects at the type level.
Inside a mapped type you can rewrite each key with an as clause: { [K in keyof T as NewKey]: ... }. Combined with template literal types, this lets you rename keys wholesale.
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};
// { name: string } -> { getName: () => string }Filtering keys
Remap a key to never and it disappears from the result. That turns key remapping into a filter — keep only the properties whose value type matches some condition:
type OnlyStrings<T> = {
[K in keyof T as T[K] extends string ? K : never]: T[K]
};Renaming plus filtering makes mapped types a genuine object-reshaping toolkit, not just a decorator.
Example
When to use it
- A mapped type renames every property in an interface to a camelCase getter name by prefixing 'get'.
- A filter remaps only properties matching a specific value type by using never to drop unwanted keys.
- An event handler map derives property names by prepending 'on' and capitalising the original key.
More examples
Remap keys with as
The as clause renames each key K to a getter-style name using a template literal with Capitalize, producing typed accessor methods.
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
interface User { name: string; age: number; }
type UserGetters = Getters<User>;
// { getName: () => string; getAge: () => number }Filter keys with never
Remaps keys to never when their value type is not string, which removes those keys from the resulting mapped type.
type OnlyStrings<T> = {
[K in keyof T as T[K] extends string ? K : never]: T[K];
};
interface Mixed { name: string; age: number; active: boolean; email: string; }
type StringOnly = OnlyStrings<Mixed>;
// { name: string; email: string }Prefix and filter combined
Combines key remapping with a string constraint and Capitalize to generate typed event handler signatures from a form schema.
type EventHandlers<T> = {
[K in keyof T as K extends string ? `on${Capitalize<K>}` : never]:
(value: T[K]) => void;
};
interface FormFields { name: string; age: number; }
type FormEvents = EventHandlers<FormFields>;
// { onName: (value: string) => void; onAge: (value: number) => void }
Discussion