Workers SDK Issue Reports

← Back to Dashboard

#9770 The types for cloudflare:test expose self as a fetcher rather than a Service breaking types when testing rpc workers

Recommendation:KEEP OPEN
Difficulty:easy
Reasoning:

SELF is typed as Fetcher without generic parameter, which doesn't expose RPC methods for WorkerEntrypoint workers

Suggested Action:

Fix types to support Service<T> or add module augmentation for user's worker type

Analysis Report

Issue Review: cloudflare/workers-sdk#9770

Summary

The SELF export in cloudflare:test is typed as Fetcher instead of Service<T>, which prevents TypeScript from recognizing RPC methods when testing workers that extend WorkerEntrypoint.

Findings

  • Created: 2025-06-26
  • Updated: 2025-07-21
  • Version: vitest-pool-workers 0.8.47 -> 0.12.6
  • Component: vitest-pool-workers
  • Labels: bug, vitest
  • Comments: 0

Key Evidence

  1. Issue is still present: The current cloudflare-test.d.ts at line 29 still shows:

    export const SELF: Fetcher;
    
  2. Root Cause: In workerd's type definitions:

    • Service<T> is a generic type that, when T is a WorkerEntrypoint, resolves to Fetcher<InstanceType<T>>
    • Fetcher<T> when T extends Rpc.EntrypointBranded provides Rpc.Provider<T> which exposes RPC methods
    • Using just Fetcher (no type parameter) defaults to Fetcher<undefined>, which only has fetch() and connect() methods
  3. No fixes found: No PRs or changelog entries reference fixing this issue

  4. Minimal reproduction info: The issue lacks a concrete reproduction example, but the problem is clear from the type definitions

Recommendation

Status: KEEP OPEN

Reasoning: The issue is valid and still affects current versions. The type definition for SELF does not support RPC methods, which breaks type-checking when testing workers that use RPC via WorkerEntrypoint.

Action: The SELF type needs to be made generic to support RPC workers.


Root Cause Analysis

The problem stems from packages/vitest-pool-workers/types/cloudflare-test.d.ts:29:

export const SELF: Fetcher;

When a user has an RPC-enabled worker like:

import { WorkerEntrypoint } from "cloudflare:workers";

export default class MyWorker extends WorkerEntrypoint {
  async fetch(request: Request) { ... }
  async myRpcMethod(arg: string): Promise<number> { ... }
}

They should be able to call SELF.myRpcMethod("test") in their tests, but TypeScript reports an error because Fetcher (without a type parameter) doesn't expose RPC methods.

The workerd types define:

  • Service<T> at types/generated-snapshot/latest/index.d.ts:2098-2110 - maps WorkerEntrypoint to the correct Fetcher<T>
  • Fetcher<T> at types/generated-snapshot/latest/index.d.ts:2111-2119 - when T extends Rpc.EntrypointBranded, provides Rpc.Provider<T> which includes RPC methods

Proposed Solution

The fix requires making SELF generic to support the user's worker type. There are two approaches:

Option A: Use Service<T> type via module augmentation (Recommended)

Allow users to augment the type via ProvidedEnv:

// In cloudflare-test.d.ts
declare module "cloudflare:test" {
  // Add a new interface for configuring the main worker type
  interface ProvidedMainWorker {}
  
  // Default to Fetcher if not specified
  type MainWorkerType = ProvidedMainWorker extends { default: infer T }
    ? Service<T>
    : Fetcher;

  export const SELF: MainWorkerType;
}

Users would then configure:

// In their test setup
import type MyWorker from "./src/index";

declare module "cloudflare:test" {
  interface ProvidedMainWorker {
    default: typeof MyWorker;
  }
}

Option B: Simpler approach using Fetcher<T>

If the vitest-pool-workers can infer the main worker's entrypoint type at build time:

// In cloudflare-test.d.ts, make SELF use Service type
export const SELF: Service<ProvidedEnv extends { __MAIN_WORKER__: infer T } ? T : undefined>;

Minimum Fix

At the very least, the type should be Service instead of Fetcher to align with how service bindings are typed elsewhere:

export const SELF: Service;

However, this alone won't fix the RPC issue since Service without a type parameter still defaults to Fetcher<undefined>.

Implementation Difficulty

Rating: Medium

Justification:

  • The fix itself is a type-only change (no runtime changes needed)
  • However, the design decision of how to let users specify their worker's type requires consideration
  • Need to ensure backward compatibility with existing tests that don't use RPC
  • Should align with how ctx.exports support was recently added (PR #11533) which uses static analysis

Files That Would Need to Be Modified

  1. packages/vitest-pool-workers/types/cloudflare-test.d.ts - Add generic type parameter support for SELF
  2. Potentially update documentation to show how users can augment the SELF type
  3. May need coordination with how additionalExports config works per PR #11533

Testing Recommendations

  1. Unit test with RPC worker: Create a test worker that extends WorkerEntrypoint with custom RPC methods and verify:

    • TypeScript correctly recognizes RPC methods on SELF
    • RPC calls work at runtime (existing behavior)
  2. Backward compatibility test: Ensure existing tests using SELF as Fetcher continue to work without modification

  3. Type-only validation: Add .test-d.ts files that verify the types are correct using expectType from tsd or similar

Suggested Comment

Thank you for reporting this issue. The root cause is that SELF is typed as Fetcher without a type parameter, which doesn't support RPC methods.

For RPC-enabled workers that extend WorkerEntrypoint, the type should be Service<T> or Fetcher<T> where T is the worker's entrypoint type. This would allow TypeScript to recognize custom RPC methods.

The fix would require either:

  1. Module augmentation to let users specify their worker type
  2. Static analysis similar to how ctx.exports support was added in #11533

Is your main worker extending WorkerEntrypoint? If you could provide a minimal reproduction showing the exact type error you're seeing, it would help validate the fix approach.

Notes & Feedback (0)

No notes yet.

Add Note