typestar

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

  1. as in a mapped type rewrites each key.
  2. Returning never from the as clause drops the key.
  3. Template literals build the new names.

Keywords and builtins used here

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.

Type this snippet

Step 2 of 3 in Mapped types, step 5 of 12 in Type-level programming.

← Previous Next →