Posts by eivindml

All posts

Avoid using barrel files with Typescript

A barrel file, often named index.ts, is used to re-export other files. For example:

// index.ts
export * from "./events"
export * from "./make-request"

This is a common pattern in TypeScript and React, especially in monorepos. For instance, in a networking library, we might use this pattern to keep imports clean:

import {getEvents, makeRequest} from "@repo/networking"

While it looks nice, I believe we should avoid using barrel files. They add an extra step every time we create a new file because we need to keep the exports in index.ts in sync. With modern code editors, like Neovim with proper LSP support, imports are automatically resolved, so we don’t need to worry too much about where files are located. The updated import paths would look like this:

import {getEvents} from "@repo/networking/event"
import {makeRequest} from "@repo/networking/make-request"

One reason for using barrel files is to control the public path for files that a package exports. Personally, I like to keep source files in a src/ folder. To hide the src/ folder from the import path, we could use a barrel file at the root or set it as the main in package.json. However, there's a better approach: using the exports field in package.json:

"exports": {
"./*": "./src/*.ts"
},

This maps the root to the src/ folder using a wildcard. Now, I can keep the src/ folder while still having clean import paths and avoiding barrel files. The .ts extension seems nececarry. Without it, my LSP imported the files with a .js extension.

Screenshot of folder structure in vim.