Skip to content

Instantly share code, notes, and snippets.

@armanozak
Last active October 1, 2020 10:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save armanozak/f01839d47348421224eb9a8b649d6f84 to your computer and use it in GitHub Desktop.
Save armanozak/f01839d47348421224eb9a8b649d6f84 to your computer and use it in GitHub Desktop.
[Variadic Tuples & Recursive Conditional Types] How tagged template literals can return type-safe functions #typescript #tip
type Repeat<T, Count, Acc extends any[] = []> = Acc['length'] extends Count ? Acc : Repeat<T, Count, [...Acc, T]>;
function i18n<Keys extends number[]>([result, ...parts]: TemplateStringsArray, ...keys: Keys) {
return (...param: Repeat<string, Keys['length']>) =>
keys.reduce((acc, key, i) => acc + (param as number[])[key] + parts[i], result);
}
const introduceEn = i18n`Hi. My name is ${0}. I work as a ${1} at ${2}.`;
const introduceTr = i18n`Merhaba. Benim adım ${0}. ${2} şirketinde ${1} olarak çalışıyorum.`;
// (param_0: string, param_1: string, param_2: string) => string
const textEn = introduceEn('Levent Arman Özak', 'software developer', 'Volosoft');
const textTr = introduceTr('Levent Arman Özak', 'yazılım geliştirici', 'Volosoft');
console.log(textEn);
// Hi. My name is Levent Arman Özak. I work as a software developer at Volosoft.
console.log(textTr);
// Merhaba. Benim adım Levent Arman Özak. Volosoft şirketinde yazılım geliştirici olarak çalışıyorum.
/* This was available before v4, but that is not the point. */
function i18n<Keys extends string[]>([result, ...parts]: TemplateStringsArray, ...keys: Keys) {
return (params: { [K in Keys[number]]: string }) =>
keys.reduce((acc, key: keyof typeof params, i) => acc + params[key] + parts[i], result);
}
const introduceEn = i18n`Hi. My name is ${'name'}. I work as a ${'occupation'} at ${'company'}.`;
const introduceTr = i18n`Merhaba. Benim adım ${'name'}. ${'company'} şirketinde ${'occupation'} olarak çalışıyorum.`;
// (params: {name: string, job: string, company: string}) => string
const textEn = introduceEn({
name: 'Levent Arman Özak',
occupation: 'developer',
company: 'Volosoft'
});
const textTr = introduceTr({
name: 'Levent Arman Özak',
occupation: 'yazılım geliştirici',
company: 'Volosoft'
});
console.log(textEn);
// Hi. My name is Levent Arman Özak. I work as a software developer at Volosoft.
console.log(textTr);
// Merhaba. Benim adım Levent Arman Özak. Volosoft şirketinde yazılım geliştirici olarak çalışıyorum.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment