Skip to content
This repository has been archived by the owner on Jun 15, 2020. It is now read-only.


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Typed Templates

Update: This project is no longer maintained since TypeScript added support for typed JSX syntax (known as TSX). See wisercode/uibuilder for a similar type of project that uses TSX, or just use the full facebook/react with TSX.

The idea is to take advantage of ES6 Tagged Template Strings and TypeScript static analysis. This work is heavily influenced by the post by It's worth a read before using this implementation.

The Problem

The problem with other templating systems is they do not work well with TypeScript and are not type safe. They usually rely on some their own DSL such as {{name}} in Handlebars. This works great for JavaScript, however we expect more from TypeScript, especially when you have a large project with hundreds of templates. Then you refactor, deploy, and cross your fingers.

The Goal

Renaming a variable should not fail siliently. Refactoring with Visual Studio (or equivalent) should change all instances of the variable, including any used inside a template. Alternatively, renaming the variable without renaming the variable used inside a template should show compile time errors.

The goal is to mimic Handlebars templates with a combination of ES6 Tagged Template Strings and escaping user input.

This does not support two-way binding or any event handling (neither does Handlebars).


Simple example:

// Create some variables
var title = 'Hello World';
var it = 'Handlebars';

// Create a template with your variables
var result = Tmpl.print `<h1>${title}</h1>
<p>Making ${it} type safe!</p>`;

// Write HTML to the DOM
document.getElementById('mydiv').innerHTML = result.getHtml();


<h1>Hello world</h1>
<p>Making Handlebars type safe!</p>

Conditional example:

const flag = 'isEnabled';
const isEnabled = false;
var p1 = Tmpl.printIf(isEnabled) `<p>The ${flag} flag is <b>ON</b></p>`;
var p2 = Tmpl.printUnless(isEnabled) `<p>The ${flag} flag is <b>OFF</b></p>`;
document.getElementById('mydiv').innerHTML = p1.getHtml() + p2.getHtml();


<p>The isEnabled flag is <b>OFF</b></p>

ForEach example:

// Define the main context
interface ListContext {
	title: string;
	subtitle: string;
	items: ItemContext[]

// Define the partial context
interface ItemContext {
	name: string;
	emotion: string;

// Create a context with some data
var context: ListContext = {
	title: 'Template Libraries',
	subtitle: 'Rendering the future obsolete',
	items: [
		{ name: "TypedTemplates", emotion: "<3" },
		{ name: "Handlebars", emotion: "like" },
		{ name: "Mustache", emotion: "enjoy" },
		{ name: "Ember", emotion: "want" }

// Define the main template
function renderList(o: ListContext) {
	var {title, subtitle, items} = o;
	return Tmpl.print `
		${Tmpl.printEach(items, renderItem)}

// Define the partial template
function renderItem(o: ItemContext) {
	var {emotion, name} = o;
	return Tmpl.print `<li>I agree. I ${emotion} ${name}.</li>`;

// Render using our example data
var result = renderList(context);

// Write HTML to the DOM
document.getElementById('my-template').innerHTML = result.getHtml();


<h1>Template Libraries</h1>
<small>Rendering the future obsolete</small>
	<li>I agree. I &lt;3 TypedTemplates.</li>
	<li>I agree. I like Handlebars.</li>
	<li>I agree. I enjoy Mustache.</li>
	<li>I agree. I want Ember.</li>

Browser support

Since we are using TypeScript, we can target ES5 and support most browsers.

  • IE 8+
  • Chrome
  • Firefox
  • node.js


🛡A typed, template module using ES6 Tagged Template Strings with TypeScript




Security policy