BUG: Type Mismatch Between DurableObject Abstract Class and DurableObject Interface for fetch Method
Abstract
I recently encountered a type mismatch issue while writing test code for Cloudflare Worker's DurableObject by @cloudflare/vitest-pool-worker. The problem arises due to the fetch method being undefined, following the example provided in honojs/examples for creating a DurableObject.
Packages
- "@cloudflare/vitest-pool-workers": "0.2.6",
- "@cloudflare/workers-types": "4.20240502.0",
- "@faker-js/faker": "~8.4.1",
- "vitest": "1.3.0",
- "wrangler": "3.53.1"
Codes
src/Matchmaking.ts
export class MatchmakingDurableObject extends DurableObject {
async addQueue(firebaseUser: FirebaseUser): Promise<void>{
// ...
}
async removeQueue(firebaseUser: FirebaseUser): Promise<void>{
// ...
}
}
test/Matchmaking.spec.ts
describe("MatchmakingDurableObject", () => {
it("Successful addQueue", async () => {
const id = env.MATCHMAKING.idFromName("matchmaking");
const stub = env.MATCHMAKING.get(id);
await runInDurableObject<MatchmakingDurableObject, DurableObjectState>(stub, async (instance, state) => {
instance.addQueue(MockFirebaseUsers[0]);
const stored = await state.storage.get("queue");
expect(stored).toBeTypeOf("string");
const queue = JSON.parse(stored as string)
expect(queue.length).toBe(1);
})
});
});
tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"skipLibCheck": true,
"lib": [
"ESNext"
],
"types": [
"@cloudflare/workers-types/experimental",
],
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx"
},
}
test/tsconfig.json
{
"extends": "../tsconfig.json",
"compilerOptions": {
"moduleResolution": "bundler",
"types": [
"@cloudflare/workers-types/experimental",
"@cloudflare/vitest-pool-workers"
]
},
"include": ["./**/*.ts", "../src/env.d.ts"]
}
Error log on vscode
Type 'MatchmakingDurableObject' does not satisfy the constraint 'DurableObject'.
Types of property 'fetch' are incompatible.
Type '((request: Request<unknown, CfProperties<unknown>>) => Response | Promise<Response>) | undefined' is not assignable to type '(request: Request<unknown, CfProperties<unknown>>) => Response | Promise<Response>'.
Type 'undefined' is not assignable to type '(request: Request<unknown, CfProperties<unknown>>) => Response | Promise<Response>'.ts(2344)
Notes
This commit of the example is just 1 week ago, so I know this is the new error. https://github.com/honojs/examples/commit/9b7acf119e874f389ca386fb2406c8f2110039e6 Temporarily I just define the fetch method on the DurableObject for the test, strangely.
So this looks like the fetch function is potentially returning undefined? It's not clear to me if this is a problem with vitest-pool-workers types or workerd DO types. Adding to the backlog to investigate further.
I am saying that there are DurableObject base class and DurableObject interface in @cloudflare/workers-types, right? So we are expecting DurableObject base class is subject to DurableObject interface, so do vitest-pool-worker. (With my understanding, class in typescript auto-generates its interface.)
But actually, DurableObject base class has a fetch method optionally, however, not optionally in DurableObject interface.
Hi @HiraiKyo,
Sorry for the delay in following up on this! Are you still seeing the types issue with the latest versions of wrangler, vitest-pool-workers, and workers-types? If so, could you share a repo that reproduces the issue?
I tried reproducing it myself but couldn't see the issue you described. It's possible that it has been resolved in a newer version 👍🏼