Skip to content

Instantly share code, notes, and snippets.

@federico-paolillo
Created October 30, 2023 13:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save federico-paolillo/0363ee603d55fb849b271216b1918390 to your computer and use it in GitHub Desktop.
Save federico-paolillo/0363ee603d55fb849b271216b1918390 to your computer and use it in GitHub Desktop.
Inspect keys like "blah blah {placeholder}" and makes a type out of them
const en = {
"key1": "my translation",
"key2": "my translation {placeholder1} {placeholder2}",
"key3": "{placeholder1} my translation",
"key4": "x {placeholder1} x",
"key5": "{placeholder1}{placeholder2}"
} as const;
type Translations = typeof en;
type TranslationKeys = keyof Translations;
// Consume {placeholders} by splitting the string in three parts: Left - Placeholder - Right
// If the string does not match Left - Placeholder - Right we return never
// Otherwise we recursively explore Left and Right and union it with Placeholder
type Placeholders<T extends string> =
T extends `${infer Left}{${infer Placeholder}}${infer Right}`
? Placeholders<Left> | Placeholder | Placeholders<Right>
: never;
type PlaceholdersOf<TKey extends TranslationKeys> =
Placeholders<Translations[TKey]> extends never
? []
: [Record<Placeholders<Translations[TKey]>, string>];
function translate<TKey extends TranslationKeys>(
key: TKey,
...placeholders: PlaceholdersOf<typeof key>
) {
}
translate('key1');
translate('key2', { placeholder1: 'a', placeholder2: 'c' });
translate('key3', { placeholder1: 's' });
translate('key4', { placeholder1: 'x' });
translate('key5', { placeholder1: 'a', placeholder2: 'c' });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment