This page covers the bun-types npm package: its file structure, how type declarations are organized, the patterns used to avoid conflicts with lib.dom.d.ts, the build process, and the integration testing harness that validates the types compile correctly.
For documentation on the Bun APIs themselves, see the relevant API pages (e.g., page 9.1 for the global Bun object, page 9.4 for the Shell API, page 9.5 for SQL APIs). For information on the bun:test testing framework, see page 6.
The packages/bun-types directory contains the bun-types npm package — a collection of TypeScript declaration files that describe the Bun runtime's public API surface. It is published independently as bun-types and is also re-exported by the @types/bun package at packages/@types/bun.
| Package | Location | Purpose |
|---|---|---|
bun-types | packages/bun-types/ | TypeScript declarations for all Bun APIs |
@types/bun | packages/@types/bun/ | Thin wrapper; references bun-types |
The package.json sets "types": "./index.d.ts" as the entry point and lists only .d.ts files, docs, and vendored types in its "files" array packages/bun-types/package.json1-36
index.d.ts is the single entry point that stitches all other declaration files together through triple-slash references.
packages/bun-types/index.d.ts reference order:
/// <reference types="node" />
/// <reference path="./globals.d.ts" />
/// <reference path="./s3.d.ts" />
/// <reference path="./fetch.d.ts" />
/// <reference path="./bun.d.ts" />
/// <reference path="./extensions.d.ts" />
/// <reference path="./devserver.d.ts" />
/// <reference path="./ffi.d.ts" />
/// <reference path="./html-rewriter.d.ts" />
/// <reference path="./jsc.d.ts" />
/// <reference path="./sqlite.d.ts" />
/// <reference path="./test.d.ts" />
/// <reference path="./wasm.d.ts" />
/// <reference path="./overrides.d.ts" />
/// <reference path="./deprecated.d.ts" />
/// <reference path="./redis.d.ts" />
/// <reference path="./shell.d.ts" />
/// <reference path="./serve.d.ts" />
/// <reference path="./sql.d.ts" />
/// <reference path="./security.d.ts" />
/// <reference path="./bundle.d.ts" />
/// <reference path="./bun.ns.d.ts" />
packages/bun-types/index.d.ts1-33
The file also declares onmessage with a special guard to prevent conflicts with lib.dom.d.ts packages/bun-types/index.d.ts31-33
Declaration file responsibilities:
| File | Module/Scope | What it declares |
|---|---|---|
globals.d.ts | Global | ReadableStream, WritableStream, Worker, WebSocket, Event, TextEncoder, TextDecoder, timer functions, etc. |
bun.d.ts | declare module "bun" | Most of the Bun namespace: file(), serve(), spawn(), build(), hashing, TOML, JSONC, JSONL, Workers, etc. |
bun.ns.d.ts | Global Bun | The globalThis.Bun namespace declaration |
overrides.d.ts | Module augmentation | Extensions to node:fs/promises, node:tls, stream/web, buffer, url, console, and NodeJS process globals |
shell.d.ts | declare module "bun" | $ tagged template, ShellPromise, ShellOutput, ShellError |
fetch.d.ts | declare module "bun" | HeadersInit, BodyInit, fetch option types |
test.d.ts | declare module "bun:test" | test, expect, Matchers, AsymmetricMatchers, mock types |
test-globals.d.ts | Global (opt-in) | test, it, describe, expect, jest, vi as globals |
s3.d.ts | declare module "bun" | S3 client API types |
sqlite.d.ts | declare module "bun:sqlite" | Database, Statement classes |
sql.d.ts | declare module "bun" | Bun.SQL PostgreSQL/MySQL client |
redis.d.ts | declare module "bun" | Valkey/Redis client |
serve.d.ts | declare module "bun" | Bun.serve() option types, Bun.Server |
ffi.d.ts | declare module "bun:ffi" | dlopen, CFunction, JSCallback |
devserver.d.ts | declare module "bun" | HMR event names, import.meta.hot types |
jsc.d.ts | declare module "bun:jsc" | JSC internal APIs |
wasm.d.ts | declare module "bun" | WebAssembly namespace extensions |
html-rewriter.d.ts | Global | HTMLRewriter API |
bundle.d.ts | declare module "bun:bundle" | feature() function, Registry interface |
deprecated.d.ts | declare module "bun" | Types marked @deprecated |
extensions.d.ts | Global | TypeScript extensions |
security.d.ts | declare module "bun" | Security-related APIs |
Sources: packages/bun-types/index.d.ts1-33 packages/bun-types/globals.d.ts1-70 packages/bun-types/overrides.d.ts1-383 packages/bun-types/test-globals.d.ts1-22 packages/bun-types/shell.d.ts1-50 packages/bun-types/fetch.d.ts1-20 packages/bun-types/bun.d.ts1-100 packages/bun-types/deprecated.d.ts1-30 packages/bun-types/devserver.d.ts1-20
Package structure and type resolution diagram:
Sources: packages/bun-types/index.d.ts1-33 packages/bun-types/package.json1-36
UseLibDomIfAvailable PatternA central challenge in bun-types is that many types (ReadableStream, Worker, WebSocket, MessageEvent, etc.) are declared both in Bun's types and in TypeScript's lib.dom.d.ts. Loading both causes redeclaration errors.
The solution is the Bun.__internal.UseLibDomIfAvailable<GlobalThisKeyName, Otherwise> conditional type, defined in bun.d.ts:
lib.dom.d.ts is loaded by testing if typeof globalThis.onabort exists.globalThis to avoid conflict.packages/bun-types/bun.d.ts49-69
This is applied extensively in globals.d.ts for ReadableStream, Worker, WebSocket, File, TextEncoder, TextDecoder, and MessageEvent:
packages/bun-types/globals.d.ts73-80
Many interfaces also use extends with conditional helpers in __internal to merge Bun-specific methods into existing types only when lib.dom.d.ts is absent. For example, interface ReadableStream<R = any> extends Bun.__internal.LibEmptyOrNodeReadableStream<R> {} packages/bun-types/globals.d.ts72
Conflict resolution pattern diagram:
Sources: packages/bun-types/bun.d.ts49-99 packages/bun-types/globals.d.ts1-80
overrides.d.tsoverrides.d.ts augments existing TypeScript and Node.js modules to add Bun-specific methods and properties. It uses declare module to extend:
| Augmented module | Added types |
|---|---|
stream/web | ReadableStream gets .text(), .bytes(), .json(), .blob() |
buffer | Blob gets .text(), .bytes(), .json(), .formData(), .arrayBuffer(), .image(), .stream() |
url | URLSearchParams.toJSON() |
console | Console[Symbol.asyncIterator] for async line iteration |
node:fs/promises | exists(path) |
node:tls | BunConnectionOptions interface, connect() override |
Global NodeJS namespace | ProcessEnv extends Bun.Env, Process.isBun, Process.revision, ProcessVersions.bun |
packages/bun-types/overrides.d.ts1-383
test-globals.d.ts is intentionally not included in index.d.ts. It must be loaded explicitly via a triple-slash directive:
This declares test, it, describe, expect, expectTypeOf, beforeAll, beforeEach, afterEach, afterAll, jest, vi, xit, xtest, and xdescribe as globals.
packages/bun-types/test-globals.d.ts1-22
The integration test validates that these do not work without the explicit reference test/integration/bun-types/bun-types.test.ts362-431
The build script at packages/bun-types/scripts/build.ts is invoked by bun run build (via package.json "scripts"). Its primary job is to stamp the current Bun version into package.json before packing.
The version is determined from process.env.BUN_VERSION, Bun.version, or process.versions.bun packages/bun-types/scripts/build.ts1-15
It also copies CLAUDE.md (a rules file for AI assistants) from src/init/rule.md into the package output.
The "test" script in package.json simply runs tsc to type-check the declarations packages/bun-types/package.json27-29
The test at test/integration/bun-types/bun-types.test.ts validates that the published bun-types package type-checks correctly under various compiler configurations.
Test setup sequence:
Sources: test/integration/bun-types/bun-types.test.ts32-85
The diagnose() function creates a ts.LanguageService with skipLibCheck: false and skipDefaultLibCheck: false to catch any type errors in the declarations themselves test/integration/bun-types/bun-types.test.ts133-241
The checkForEmptyInterfaces() function scans for global interface symbols with no properties, call signatures, construct signatures, or index signatures. Empty interfaces indicate accidental type erasure from the UseLibDomIfAvailable pattern test/integration/bun-types/bun-types.test.ts243-294
Fixture files tested:
| Fixture file | What it exercises |
|---|---|
fixture/index.ts | General Bun API surface: Bun.file, Bun.serve, Bun.spawn, Shell $, S3, Streams, etc. |
fixture/spawn.ts | Bun.spawn() / Bun.spawnSync() type inference for stdio configurations |
fixture/streams.ts | ReadableStream, WritableStream, TransformStream with Bun extensions |
fixture/crypto.ts | crypto.subtle, SubtleCrypto, CryptoKey types |
fixture/websocket.ts | WebSocket constructor overloads and Bun-specific options |
fixture/serve-types.test.ts | Bun.serve() options, Bun.Server<T> generic |
fixture/globals.ts | Bun.file(), global APIs, fs compatibility |
fixture/env.ts | Bun.Env, NodeJS.ProcessEnv, ImportMetaEnv augmentation |
fixture/http.ts | node:http compatibility |
fixture/bun.ts | BunPlugin, FileBlob imports |
Sources: test/integration/bun-types/bun-types.test.ts310-511 test/integration/bun-types/fixture/index.ts1-50 test/integration/bun-types/fixture/spawn.ts1-40
The suite also tests tsgo (TypeScript 7's native Go-based compiler) by writing a real tsconfig.json and spawning the CLI test/integration/bun-types/bun-types.test.ts320-347
bun:bundle Registry Patternbundle.d.ts declares the bun:bundle module, which exports a feature() function. The argument type of feature() is driven by a user-augmentable Registry interface:
When Registry.features is not defined, feature() accepts any string. When augmented, only the declared union members are accepted. This is validated by the integration tests test/integration/bun-types/bun-types.test.ts433-511
bun.d.ts Namespace InternalsThe bun.d.ts file declares the "bun" module with all top-level Bun APIs. The Bun.__internal namespace contains several utility types used throughout the file:
| Internal type | Purpose |
|---|---|
LibDomIsLoaded | true if onabort is on globalThis (i.e., lib.dom.d.ts is loaded) |
UseLibDomIfAvailable<K, T> | Conditional type to avoid DOM conflicts |
DistributedOmit<T, K> | Omit that distributes over unions |
KeysInBoth<A, B> | Intersection of keys from two types |
Merge<A, B> | Merges two types, unioning overlapping keys |
DistributedMerge<T, Else> | Merge that distributes over unions |
Without<A, B> | Excludes B's non-A keys as never (XOR helper) |
XOR<A, B> | Exclusive-OR of two types |
packages/bun-types/bun.d.ts49-99
The Bun.Env interface (with NODE_ENV and TZ) is designed for user augmentation. NodeJS.ProcessEnv extends it via overrides.d.ts, meaning custom properties declared in Bun.Env propagate to process.env packages/bun-types/overrides.d.ts74-77
The workspace bun.lock lists both packages/bun-types and packages/@types/bun as local workspace packages bun.lock23-35
The @types/bun package is a thin shim that re-exports bun-types via:
This follows the @types/* DefinitelyTyped convention and enables users to add Bun types with bun add -d @types/bun without directly depending on bun-types.
The integration test creates a tarball from the local package and installs it into an isolated fixture directory to test exactly what gets published test/integration/bun-types/bun-types.test.ts41-84
Sources: packages/bun-types/scripts/build.ts1-15 packages/bun-types/package.json1-36 bun.lock23-35 test/integration/bun-types/bun-types.test.ts32-85
Refresh this wiki
This wiki was recently refreshed. Please wait 1 day to refresh again.