Typescript/TSX in (Doom) Emacs 29+

  1. emacs
  2. typescript


I still don’t like TypeScript, but with the current trend of front-end development, it’s hard to avoid.

To work with it in Emacs, I’ve been using the “hacks” I mentioned in my previous post Better TSX support w/ Tree-sitter in Doom Emacs. However, with the coming Emacs 29 release, this all changes. It has built-in support for Tree-sitter, including TypeScript/TSX modes, so I no longer need to use those hacks.

Tree-sitter in Emacs 29

Tree-sitter is a big deal in text editors lately. And now even Emacs is getting in on the action.

In the Emacs 29 release branch, we not only have built-in Tree-sitter support, but also many Tree-sitter powered major modes, including TypeScript/TSX.

These new major modes are developed by the maintainers of the typescript-mode package, who have stopped maintaining the old typescript-mode package. As a result, we can expect the new Tree-sitter based major mode to be more stable and feature-rich. IMO, it’s already better than the old typescript-mode package, and it’s the best new Tree-sitter based major mode in Emacs 29.

Start using it now

Install Emacs 29

Firstly, ensure that you are using Emacs 29. If you are on Gentoo, simply sync the emacs-29 version and select it with eselect. Don’t forget to enable the tree-sitter USE flag.

echo '>=app-editors/emacs-29.0.9999 tree-sitter' | sudo tee -a /etc/portage/package.use/emacs

sudo emerge -av =emacs-29.0.9999-r1
sudo eselect emacs set emacs-29-vcs

I’m sure you can find a way to install it on your system too.

Prepare tree-sitter libraries

Although the built-in support is available, there are still some hassles to get it working properly. You need to install the grammar files for the major modes you want to use and enable the tree-sitter-based major modes in your configuration.

treesit-auto is a package to minimizes the hassle, but since I only want to use the TypeScript/TSX major modes, I prefer to do it manually.

(after! treesit
  (setq treesit-language-source-alist
        '((typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src" nil nil)
          (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src" nil nil))))

After evaluating the code above, run M-x treesit-install-language-grammar, and select typescript and tsx, This convenient function is provided by the built-in treesit package. It will download and build the grammar files for you, and install them in the correct place.

Use the new major modes

Now, you can activate the new major modes in your config, and you are good to go, you can skip the lsp part if you don’t use lsp of course.

(use-package typescript-ts-mode
  :mode (("\\.ts\\'" . typescript-ts-mode)
         ("\\.tsx\\'" . tsx-ts-mode))
  (add-hook! '(typescript-ts-mode-hook tsx-ts-mode-hook) #'lsp!))

optionally, you can disable the typescript-mode package.

(package! typescript-mode :disable t)

“Electric Pair”

The new major modes works great, but there is this one thing I miss from the rjsx-mode: the “electric pair” feature, which automatically insert the closing tag when you type the opening tag.

I tried to do the same hack as I did in the previous post, but it doesn’t work, since rjsx-minor-mode relies on js2-mode to build the syntax tree, and I don’t think it works well with the Typescript syntax.

I really hope I can get this feature in the new typescript-tsx-mode, maybe even trying to implement it myself, let’s see.

Non Doom Emacs

This post discusses how to use it in Doom Emacs, but it doesn’t use any Doom-specific features or packages other than the configuration macros, so it should be easy to port to vanilla Emacs.


As you can see, this is way easier to work with typescript/tsx in emacs 29 now, and all the hack config I mentioned in my previous post is no longer needed, and I’m happy to delete them.