Typescript in Hugo

I’ve been playing with webmentions in Hugo my goal is to have the webmentions displayed initialy using javascript/typescript, and every time the site is built the webmentions are pulled into the site and servered statically.

For this I need to write some custom javascript. (I’m sure there is already a system which will do this, but wheres the fun in that.) I prefer typescript over javascript, the added type safety and IDE features just makes it easier to use.

Hugo supports typescript out of the box, using esbuild behind the sceens to compile the code. This is great as it makes it really fast to build and test.

There are a few steps to get it up and running,

Here is an example typescript file which takes a String, converts it to an array, sorts it, removes duplicate values, and returns the array. Just as an example.

// assets/ts/app/test.ts

export function orderAndUniquify(str: string): string[] {
    return [...Array.from(new Set(str.split("").sort()))];
}

Now we need to use it in our Hugo templates to do this we need to first tell hugo to build the file.

{{ $test := resources.Get "/ts/app/test.ts" | js.Build (dict "format" "esm") }}

Here we have told hugo to get the resource at /assets/ts/app/test.ts pass it to esbuild, and assign the result to $test.

You’ll have noticed the (dict "format" "esm"), this passes arguments to esbuild to tell it to build an esm module. without this it would be built as an immediately invoked function, not much use for out function.

Now we have out $test variable we can use it in our script tags.

{{ $test := resources.Get "/ts/app/test.ts" | js.Build (dict "format" "esm") }}
<script type="module">
    import { orderAndUniquify } from "{{ $test.Permalink }}";
    console.log(orderAndUniquify("Hello World"));
</script>

Here we have added to our code, to import the resultant javascript file using the automatically generated Permalink, and using the imported function.