Bun

TypeScript

Bun treats TypeScript as a first-class citizen.

Running .ts files

Bun can directly execute .ts and .tsx files just like vanilla JavaScript, with no extra configuration. If you import a .ts or .tsx file (or an npm module that exports these files), Bun internally transpiles it into JavaScript then executes the file.

Note — Similar to other build tools, Bun does not typecheck the files. Use tsc (the official TypeScript CLI) if you're looking to catch static type errors.

Is transpiling still necessary? — Because Bun can directly execute TypeScript, you may not need to transpile your TypeScript to run in production. Bun internally transpiles every file it executes (both .js and .ts), so the additional overhead of directly executing your .ts/.tsx source files is negligible.

That said, if you are using Bun as a development tool but still targeting Node.js or browsers in production, you'll still need to transpile.

Configuring tsconfig.json

Bun supports a number of features that TypeScript doesn't support by default, such as extensioned imports, top-level await, and exports conditions. It also implements global APIs like the Bun. To enable these features, your tsconfig.json must be configured properly.

If you initialized your project with bun init, everything is already configured properly.

To get started, install the bun-types package.

bun add -d bun-types # dev dependency

If you're using a canary build of Bun, use the canary tag. The canary package is updated on every commit to the main branch.

bun add -d bun-types@canary

Recommended compilerOptions

These are the recommended compilerOptions for a Bun project.

{
  "compilerOptions": {
    // add Bun type definitions
    "types": ["bun-types"],

    // enable latest features
    "lib": ["esnext"],
    "module": "esnext",
    "target": "esnext",

    // if TS 5.x+
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "moduleDetection": "force",
    // if TS 4.x or earlier
    "moduleResolution": "nodenext",

    "jsx": "react-jsx", // support JSX
    "allowJs": true, // allow importing `.js` from `.ts`
    "esModuleInterop": true, // allow default imports for CommonJS modules

    // best practices
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true
  }
}

Path mapping

When resolving modules, Bun's runtime respects path mappings defined in compilerOptions.paths in your tsconfig.json. No other runtime does this.

Given the following tsconfig.json...

{
  "compilerOptions": {
    "paths": {
      "data": ["./data.ts"]
    }
  }
}

...the import from "data" will work as expected.

index.ts
data.ts
index.ts
import { foo } from "data";
console.log(foo); // => "Hello world!"
data.ts
export const foo = "Hello world!"