My Experience with Typst So Far

I’ve been trying Typst in my work for some time. For those of you who don’t know, Typst is a new language/tool for typsetting technical documents. Its goal is to be a better alternative to (La)TeX, which as probably everyone in the academia would agree, has not been pleasant to use. Different people might have different problems with LaTeX. For me, it’s mostly the gibberish error messages (such as “Undefined control sequence” followed by some weird string I’ve never seen), confusing package compatibility (some package for some reason can’t be used together with a package in the dependencies of acmart?), difficult-to-access documentation (why are packages documented in a book-like PDF files?), and bad tooling (maybe because of this). Based on my experience so far with Typst, it does fix those problems pretty well.

The Language

Core to what makes everything suddenly so much nicer in Typst is the language itself. You can treat it as if you were dealing with something as simple as Markdown, but all those things you see are just syntax sugar. Under the hood it is a proper Turing-complete programming language. Two nice things I have noticed about the language so far:

  • Typed. It is handling actual data of specific types that can’t be mixed up. Compare that with (La)TeX where with the exception of primitives it’s all just pattern matching on text and macro expansions (TeX has character codes but those are token-level and only used to guide parsing).
  • Purely functional. This means
    • We can tweak whatever settings in a context like a paragraph without worrying about it conflicting with anything outside, because it has no side effects when viewed from outside. For example, I can define a bunch of functions in my template library tweaking the styles in all kinds of crazy ways, but a user doesn’t need to worry about it affecting things that are not output from those functions. If I have a document A and need to create a second document B that needs to reuse some content from A, I can simply bind that content to a name through let, import A and reference it in B. I don’t need to worry about messing up B’s formatting with A’s.
    • We can memoise the results due to referential transparency. My understanding is that this is the main enabler of incremental compilation in Typst. I’m using Typst with the “Typst Preview” VSCode extension, and it can update the rendered file instantaneously when I type. This makes up a lot for not being WYSIWYG like Word.

Bells and whistles

The show rule is just like CSS rules which allow the user to set attributes for elements selected by selectors. I find it a convenient way to quickly highlight specific keywords. Since regex is allowed in selectors this can also be a quick and dirty way to provide basic syntax highlighting for code blocks.

The “Typst Preview” extension also supports jumping between the render output and the source file (similar to what SyncTeX does) which I find very convenient.


I think Typst has the ambition to dethrone LaTeX so in the end it would need to support whatever LaTeX currently supports. Most things are quite clean with the language design discussed above, but it seems that there are places where the language design can make it harder to do things. One example I have encountered is with the double-column layout. It is quite common that in a double-column document, one needs to make a few selected elements (e.g., a table or a figure) span the whole page width. As far as I know, this is not currently possible with Typst. Perhaps this is fundamentally tricky given the purely functional language design. For example, right now if we put some content in a columns(2) environment, that content is just going to split into a two columns. If another columns(3) is nested inside it, each of the two columns is going to be split further into three columns. Now, if inside columns(3) we want to have a wide table, should that table span a column of the outer columns(2) environment, or the full page width? It’s unclear how to decide between the two options without knowledge about the outside context. Moreover, now something inside columns(3) could have global side-effects (disrupting the whole page layout).


The documentation of the standard library is available as searchable web pages, and they have planned to set up a central documentation hosting platform like too.


I created presentation slides with Polylux (there are other packages for slides but they look the same so I just pick one that seems most popular). For basic animations that just involve hiding and unhiding things, it’s already quite usable. However, animations that require changing attributes are a bit tricky and the current way to do this is to basically pass the different versions in alternatives. Defining a function to output both (selected by the function argument) saves some copy-pasting but even for very simple tasks it still requires cluttering the document with one-off boilerplate-like functions.


Right now Typst still has some limitations in terms of the functionality. It also lacks support from major journals and conferences. Those problems are holding me back from using Typst for writing papers. However, I’m happy to use it as much as I can for less complex tasks and personal notes while waiting for Typst to mature more. I have little doubt that Typst will become widely adopted to the point that publication venues start providing official support, and that will probably be soon.