I'm trying to create a CloudFlare Worker using the itty-router. Following the guide on TypeScript we have to define the TypeScript types as in the code below.
The code works fine but there's a TypeScript error in the part async...
:
Argument of type '({ content }: IRequest, env: Args[0], ctx: Args[1]) => Promise<{ success: boolean; status: number; data: { [key: string]: any; }; error: null; } | { success: boolean; status: number; data: null; error: any; }>' is not assignable to parameter of type 'RequestHandler<IRequest, []>'.
Target signature provides too few arguments. Expected 3 or more, but got 1.ts(2345)
import { createClient } from '@supabase/supabase-js'
import { AutoRouter, IRequest, withContent } from 'itty-router'
interface Env {
SUPABASE_URL: string
SUPABASE_KEY: string
}
type CFArgs = [Env, ExecutionContext]
const router = AutoRouter<IRequest, CFArgs>()
router.post(
'/clients',
withContent,
async ({ content }, env, ctx) => {
try {
const body = content as { [key: string]: any }
const newClient = { ...body }
const supabase = createClient(env.SUPABASE_URL, env.SUPABASE_KEY)
const { data, error } = await supabase.from('clients').insert(newClient)
if (error) throw new Error(`Supabase error: ${error.message}`)
return {
success: true,
status: 200,
data: newClient,
error: null,
}
} catch (error: any) {
return { success: false, status: 500, data: null, error: error.message }
}
}
)
There are a couple of ways around this, but the easiest is to redeclare the generics on the route itself:
const router = AutoRouter<IRequest, CFArgs>()
router.post<IRequest, CFArgs>( // add the generics here
'/clients',
withContent,
async ({ content }, env, ctx) => {
// handler internals
}
)
Additionally, should you ever try to abstract these into an external handler, you'll want to type them at the handler level before you can add them into the route flow (to avoid TS errors). This will make more sense below:
const handler1 = async ({ content }, env, ctx) => {} // BAD
const handler2 = async ({ content }: IRequest, env: Env, ctx: ExecutionContext) => {} // GOOD
const handler3: RequestHandler<IRequest, CFArgs> = async ({ content }, env, ctx) => {} // GOOD
router.post<IRequest, CFArgs>(
'/clients',
withContent,
handler1, // TS error
handler2, // this is fine
handler3, // this is fine
async ({ content }, env, ctx) => {
// handler internals
}
)