Задача, которая встречается почти в каждом проекте - это создание параметризированных строк. Чаще всего подобные конструкции можно встретить роутерах, но применение можно найти во многих других местах. Обычно это выглядит примерно так:
const postURL = template('{host}/posts/{id}'); const url = postURL({ host: 'http://example.com', id: 1 }); // url === 'http://example.com/posts/id' Реализовать подобное API не представляет большой сложности. Разбиваем строку с помощью регулярного выражения, подставляя реальные значения вместо переменных.
// создаем regexp для разбиения const buildSeparatorVarRx = (start: string, end: string) => new RegExp(`${start}([^${start + end}]+)${end}`); // в качестве разделителя используем скобки const rx = buildSeparatorVarRx('\\{', '\\}'); export function template<T extends string>(tmpl: T) { const array = tmpl.split(rx); // TTemplateFunction - ??? const fn: TTemplateFunction<T> = args => array.map((item, i) => (i % 2 ? (args as Record<string, string | number>)[item] : item)).join('') as any; return fn; } Данная реализация отвечает на все наши запросы, но остается под вопросом что такое TTemplateFunction? Он конструирует из литеральной строки (string literal types) T тип-функцию, которой на вход передается объект, ключи которого должны соответствовать переменным из типа T. Возвращаемое значение будет литеральной строкой с подставленными значениями из аргументов вместо переменных из T.
...