npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

typlate

v0.0.10

Published

Typesafe templates for TypeScript

Downloads

292

Readme

A simple templating language that generates typesafe TypeScript.

Why use this instead of template strings?

Indentation and syntax highlighting can be annoying for long template strings that are mostly text.

This was originally built for managing long documents to send to LLMs; the documents are mostly Markdown text with a few interpolated variables. Conserving tokens is important (i.e. you don't want long strings of extra space charactes, since they'll count against your token limit), so template strings are gonna have pretty weird indentation if you use them.

Getting started

npm install -g typlate

# Compile templates in ./template-dir, and put the generated code in ./generated
typlate --outdir ./generated ./template-dir

Guide

Typlate lets you use ERB-style templating to generate typesafe TypeScript. You can import the generated code into your existing TypeScript codebase, and ensure that your templates are 1:1 in sync with your code: you can't forget to pass in a variable at runtime, since TypeScript will check your templates at compile-time.

For example:

<%--
  // This is the head block, similar to YAML frontmatter. It will always go at
  // the top of the file, so define your arguments + any imports here

  // You always need to define your template args in an Args type
  type Args = {
    listingName: string,
    description: string,
    dollars: number,
    cents: number,
  };
%>

# <%= args.listingName %>

<%= args.description %>

Book for only $<%= args.dollars %>.<%= args.cents %>!

As you can see, <%= ... %> tags print out the values of expressions in the template, just like ERB files. The template provides an args variable that contains the arguments specified in the Args type.

Statements

If you need to do more than just print out variables, you can use <% ... %> blocks, which accept statements, and don't by themselves print anything. For example:

<%--
  type Args = {
    lines: string[]
  };
%>

Here are some lines of code:

<% for(const line of args.lines) { %>
  <%= line %>
<% } %>

You can use these for any kind of statements, not just for loops: it's just ordinary TypeScript. For example:

<%--
  type Args = {
    count: number,
  };
%>

Here's FizzBuzz up to <%= args.count %>:

<%
  function fizzbuzz(i: number) {
    const els = [];
    if(i % 3 === 0) els.push("fizz");
    if(i % 5 === 0) els.push("buzz");
    if(els.length === 0) els.push(i);
    return els.join("");
  }

  for(let i = 0; i < args.count; i++) { %>
    <%= fizzbuzz(i) %>
<% } %>

Importing into TypeScript

First, make sure you've compiled the templates by running the typlate command. Then:

import render from "./path/to/generated/code";

render({
  // ...
});

Typlate templates also include their original filepath, exported as a variable. So if you want to track the original path of your compiled template, you can do:

import { filepath } from "./path/to/generated/code";

Partials

Since templates simply compile to functions, and you can write arbitrary TypeScript in your templates, just import the partials and call them as functions. We've added a special TyplateArgs type to infer the arguments of an imported template, so you can easily reuse them without re-typing:

<%--
  import linesOfCode from "./lines-of-code.md";

  type Args = {
    examples: Array<{
      name: string,
      args: TyplateArgs<typeof linesOfCode>,
    }>
  }
%>

# Coding examples:

<% for(const example of args.examples) { %>
## <%= example.name %>
<%= linesOfCode(example.args) %>
<% } %>