cloudflare / cloudflare/workerd

workers-types declares Buffer and process as const, discarding the @types/node globals

Open Beginner friendly
#7,026 2 comments 1 reaction 0 assignees View on GitHub
Dominant language
C++
Stars
8.7k
Forks
739
Avg merge
2d 20h
Merged PRs (30d)
174

Description

`@cloudflare/workers-types` declares `Buffer` and `process` as `const`, which discards the `@types/node` globals in any project that uses both.

`index.d.ts` (lines 486–487 in `5.20260817.1`):

```ts
declare const Buffer: any;
declare const process: any;
```

`@types/node` declares `var Buffer: BufferConstructor` inside `declare global { … }` in `buffer.buffer.d.ts`. **A `var` merges across declaration files; a block-scoped `const` does not.** The redeclaration discards the `@types/node` global block, and ordinary Node code stops type-checking.

**Affected:** any project listing both `@cloudflare/workers-types` and `node` in `compilerOptions.types`.

| | |
|---|---|
| First affected version | **`5.20260807.2`** |
| Last clean version | **`5.20260804.1`** |
| Still present in | **`5.20260817.1`** (current `latest`) |

Bisected by unpacking each published tarball and grepping `index.d.ts`, so the boundary is exact rather than inferred from a changelog. Ten consecutive releases now carry it.

## Reproduction

`package.json` — `@cloudflare/workers-types@5.20260817.1`, `@types/node@22.20.1`, `typescript@5.9.3`.

`tsconfig.json`:

```json
{
"compilerOptions": {
"types": ["node", "@cloudflare/workers-types"],
"strict": true,
"skipLibCheck": true,
"noEmit": true
},
"include": ["src"]
}
```

`src/index.ts`:

```ts
import { randomBytes } from "node:crypto";
export const id = (): string => randomBytes(8).toString("hex");
```

`tsc --noEmit`:

```
src/index.ts(2,50): error TS2554: Expected 0 arguments, but got 1.
```

## The real error, which `skipLibCheck` hides

With `skipLibCheck: false` TypeScript states the actual problem:

```
node_modules/@cloudflare/workers-types/index.d.ts(486,15): error TS2451: Cannot redeclare block-scoped variable 'Buffer'.
node_modules/@types/node/buffer.buffer.d.ts(356,19): error TS2451: Cannot redeclare block-scoped variable 'Buffer'.
```

`skipLibCheck: true` — the default in most templates, including Cloudflare's own — suppresses the `TS2451` and leaves only the downstream `TS2554`. That is why this presents as a mystery about `randomBytes` rather than as a redeclaration. A type probe shows `randomBytes(8).toString` resolving to `() => string`, i.e. `Uint8Array.prototype.toString`, because the `Buffer` interface members in the discarded global block are gone.

## Isolated

Each row run, not reasoned about:

| change | result |
|---|---|
| `types` order reversed | still fails — ordering is irrelevant |
| `types: ["node"]` alone | clean |
| pin `5.20260804.1` | clean |
| `declare const` → `declare var` on both lines | **clean** |
| delete both lines | **clean** |
| delete the `process` line only | still fails — `Buffer` alone is the cause |
| delete the `Buffer` line only | clean |

## `process` has the same collision, and it is silent

`declare const process: any` collides with `@types/node`'s `var process` identically. It produces no error only because `any` absorbs every member access — so rather than failing, it **silently degrades `process` from `NodeJS.Process` to `any`**. Anyone with both type sets has lost that typing without being told.

## Suggested fix

Declare them as `var`, which merges with `@types/node` rather than colliding with it:

```ts
declare var Buffer: any;
declare var process: any;
```

Or do not emit them at all — a Workers project that wants `Buffer` or `process` types installs `@types/node` and sets `nodejs_compat`, and gets the real declarations rather than `any`.

## Prior art

`cloudflare/workerd#1298` — *"Transitive loading of `@types/node` breaks Request/Response (etc.) types"* — is the same collision class pointing the other way: `@types/node` clobbering `workers-types` when Node began declaring its own `Request`/`Response`. This is the mirror image.

---

Found while pinning dependency floors ahead of a first release of a Workers framework built on workerd. Happy to open a PR with the `const` → `var` change if that is the preferred fix.

Contributor guide

Open the contributing guide

Research direction

Start at index.d.ts lines 486–487 and inspect how the global Buffer and process declarations interact with @types/node. Reproduce the issue with the listed package versions and tsconfig, then run tsc with both type packages enabled. Done means Node’s Buffer and process globals retain their normal typings and the reproduction type-checks cleanly.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
developer-experience, tooling
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.