T
TanStack15h ago
xenial-black

Issue with Generic Handler Factory for TanStack Start Routes

I'm trying to create a reusable handler factory pattern for TanStack Start API routes The Problem: The RouteMethodHandlerCtx type requires 5 generics, including a specific route path as the 3rd generic parameter (e.g., '/demo/api/endpoint-factory'). When I try to make my factory generic to work with any route, I can't properly type the route path parameter. What I'm trying to achieve: A reusable handler factory that: - Works with any TanStack Start API route - Maintains full type safety How can I properly type the generic constraints for RouteMethodHandlerCtx to make this factory pattern work across different routes while maintaining type safety? Prepared this example to give you an idea of what I am trying to build. The factory works when I hardcode the exact route path, but then it's not reusable across different routes. I need it to be generic
import { createFileRoute } from '@tanstack/react-router'
import type { AnyRoute, Register } from '@tanstack/react-router'
import type { RouteMethodHandlerCtx } from '@tanstack/react-start'

const handlerFactory = <
TCtx extends RouteMethodHandlerCtx<
Register,
AnyRoute,
'/demo/api/endpoint-factory',
unknown,
any
>,
>(
handler: (ctx: TCtx, headerId: string) => Response | Promise<Response>,
) => {
return async (ctx: TCtx) => {
const headerId = ctx.request.headers.get('x-custom-id') || 'no-id'
return handler(ctx, headerId)
}
}

export const Route = createFileRoute('/demo/api/endpoint-factory')({
server: {
handlers: {
POST: (ctx) => {
const headerId = ctx.request.headers.get('x-custom-id') || 'no-id'
return new Response(
`Hello from endpoint factory! Header ID: ${headerId}`,
)
},
GET: handlerFactory((ctx, headerId) => {
return new Response(
`Hello from endpoint factory! Header ID: ${headerId}`,
)
}),
},
},
})
import { createFileRoute } from '@tanstack/react-router'
import type { AnyRoute, Register } from '@tanstack/react-router'
import type { RouteMethodHandlerCtx } from '@tanstack/react-start'

const handlerFactory = <
TCtx extends RouteMethodHandlerCtx<
Register,
AnyRoute,
'/demo/api/endpoint-factory',
unknown,
any
>,
>(
handler: (ctx: TCtx, headerId: string) => Response | Promise<Response>,
) => {
return async (ctx: TCtx) => {
const headerId = ctx.request.headers.get('x-custom-id') || 'no-id'
return handler(ctx, headerId)
}
}

export const Route = createFileRoute('/demo/api/endpoint-factory')({
server: {
handlers: {
POST: (ctx) => {
const headerId = ctx.request.headers.get('x-custom-id') || 'no-id'
return new Response(
`Hello from endpoint factory! Header ID: ${headerId}`,
)
},
GET: handlerFactory((ctx, headerId) => {
return new Response(
`Hello from endpoint factory! Header ID: ${headerId}`,
)
}),
},
},
})
0 Replies
No replies yetBe the first to reply to this messageJoin

Did you find this page helpful?