Mapped types with key remapping in TypeScript
Building a type from another one, renaming the keys as you go.
interface Settings {
theme: string;
editorMode: boolean;
timeLimit: number;
}
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
type OnlyBooleans<T> = {
[K in keyof T as T[K] extends boolean ? K : never]: T[K];
};
type Nullable<T> = { [K in keyof T]: T[K] | null };
type SettingsGetters = Getters<Settings>;
type Flags = OnlyBooleans<Settings>;
const getters: SettingsGetters = {
getTheme: () => "dracula",
getEditorMode: () => true,
getTimeLimit: () => 60,
};
const flags: Flags = { editorMode: false };
const nullable: Nullable<Settings> = { theme: null, editorMode: true,
timeLimit: 30 };
console.log(getters.getTheme(), flags.editorMode, nullable.theme);
How it works
asin a mapped type rewrites each key.- Returning
neverfrom theasclause drops the key. - Template literals build the new names.
Keywords and builtins used here
FlagsNullableSettingsGettersasbooleanconstextendsfalseinterfacenevernullnumberstringtruetype
The run, in numbers
- Lines
- 28
- Characters to type
- 698
- Tokens
- 203
- Three-star pace
- 110 tpm
At the three-star pace of 110 tokens a minute, this run takes about 111 seconds.
Step 2 of 3 in Mapped types, step 5 of 12 in Type-level programming.