Your config files should be typechecked

aka, How to use the power of Typescript for your Prettier, ESLint and other config files

Jan 12, 2022 · programming, javascript

Or maybe not, whatever fits your needs. Personally, I think that definitely not enough people are using TypeScript for their config files, or maybe not a lot of people know that you even can in the first place!

Luckily, we're entering an era of many projects having their config files typechecked as a first-class option, for instance Vite supports it through three(!) different methods, Astro ships typechecked config files in all of its starters and most projects Anthony Fu has worked on have typechecked config files, himself being a proponent of typing your config files

However, not every project has caught up yet. Here's an example: Have you ever tried writing by hand an ESLint or Prettier config only to realize that you don't know half of the settings (and their values) it can takes? Well, TypeScript can, and will, help you with that! ✨

Let's see how we can use typed configs with some of the most popular JavaScript tools!

On .ts config files and helper methods

Unfortunately, most tools do not support just using a .ts extension or using an helper method, so we'll have to use JSDoc type annotations to achieve this

While this is unfortunate, luckily JSDoc annotations are just as easy to use!

ESLint

First install the DefinitelyTyped's type definition for ESLint, @types/eslint using your favorite package manager. And then, in your eslintrc.js file, write the following

/** @type {import("@types/eslint").Linter.Config */
module.exports = {
  // ... your eslint config here
};

And there you go, your ESLint config is now typechecked by TypeScript which also means that you now get suggestions and completions through your editor! It's fun AND interactive!

Let's do the same thing for Prettier!

Prettier

Similarly to ESLint, first install the types definition for Prettier through @types/prettier and then add the following to your .prettierrc.js

/** @type {import("@types/prettier").Options */
module.exports = {
  // ... your prettier config here
};

It's that easy and the benefits are very clear immediately. Frankly, in my opinion it's worth it for the completion alone, so convenient. Let's do more!

Tailwind

Tailwind ships types directly. They're unfortunately not that great, but it's an improvement over nothing!

/** @type {import('tailwindcss').Config} */
module.exports = {
  // ... your tailwind config here
};

Bonus: Astro

As said in the intro of this article, Astro starters are all using Typescript for their config file through a JSDoc comment, but we can do even better by directly using a .ts file!

import type { AstroUserConfig } from "astro";

const config: AstroUserConfig = {
  // ... your astro config here
};

export default config;