Last active
June 28, 2024 13:09
-
-
Save JTRNS/0a5745e5089c819ef2f96abb9938edd9 to your computer and use it in GitHub Desktop.
Type Safe Templates
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Delimiter = ",\n"|"," | "." | "?" | "!" | "\n" | |
type IsTemplateTag<Word> = Word extends `{${infer TagName}}${Delimiter}${string}` ? TagName : never; | |
// type IsTemplateTag<Word> = Word extends `{${infer TagName}}` ? TagName : isTemplateTagWithComma<Word>; | |
// type isTemplateTagWithComma<Word> = Word extends `{${infer Tagname}},` ? Tagname : isTemplateTagWithPeriod<Word>; | |
// type isTemplateTagWithPeriod<Word> = Word extends `{${infer Tagname}}.` ? Tagname : never; | |
type TemplateTags<TemplateString> = TemplateString extends | |
`${infer PartA} ${infer PartB}` ? IsTemplateTag<PartA> | TemplateTags<PartB> | |
: IsTemplateTag<TemplateString>; | |
type TemplateParams<T extends string> = { | |
[Key in TemplateTags<T>]: { | |
toString(): string; | |
}; | |
}; | |
type TemplateRenderFunc<T extends string> = ( | |
params: TemplateParams<T>, | |
) => string; | |
export function parseTemplateString<T extends string>( | |
str: T, | |
): TemplateRenderFunc<T> { | |
const tags = [...str.matchAll(/{\w+}/g)].flat(); | |
function render<U extends TemplateParams<T>>(params: U): string { | |
// check for missing params | |
if ( | |
tags.some((tag) => !Object.keys(params).includes(tag.slice(1, -1))) | |
) { | |
throw new Error( | |
`Missing template parameter. Required: ${tags.join(", ")} Received: ${ | |
Object.keys(params).join(", ") | |
}`, | |
); | |
} | |
let result: string = str; | |
for (const key in params) { | |
const value = params[key]; | |
result = result.replaceAll(`{${key}}`, value.toString()); | |
} | |
return result; | |
} | |
return render; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment