Create a utility method. // handleMethods.ts type ApiResponse < Data = {}, Error = { message : string } > = | { result : true ; data : Data } | { result : false ; data : Error } export const handleMethods = < Q extends Record < string , string > = {} > () => { const handlers : { [ key : string ]: NextApiHandler | undefined } = {} const methodHandler = { get : < T , E = string > ( handler : ( req : NextApiRequest & { query : Q }, res : NextApiResponse < ApiResponse < T , E >> , ) => void | Promise < void > , ) => { handlers [ ' GET ' ] = handler return methodHandler }, post : < T , E = string > ( handler : ( req : NextApiRequest & { query : Q }, res : NextApiResponse < ApiResponse < T , E >> , ) => void | Promise < void > , ) => { handlers [ ' POST ' ] = handler return methodHandler }, put : < T , E = string > ( handler : ( req : NextApiRequest & { query : Q }, res : NextApiResponse < ApiResponse < T , E >> , ) => void | Promise < void > , ) => { handlers [ ' PUT ' ] = handler return methodHandler }, delete : < T , E = string > ( handler : ( req : NextApiRequest & { query : Q }, res : NextApiResponse < ApiResponse < T , E >> , ) => void | Promise < void > , ) => { handlers [ ' DELETE ' ] = handler return methodHandler }, prepare : (): NextApiHandler < ApiResponse > => ( req , res ) => { if ( handlers [ req . method ]) { return handlers [ req . method ]( req , res ) } else { return res . status ( 404 ). json ({ result : false , data : { message : ' not found ' } }) } }, } return methodHandler }
Enter fullscreen mode Exit fullscreen mode Usage // pages/api/users/index.ts type User = {...} export default handleMethods () . get < Array < User >> ( async ( req , res ) => { try { const result = await findUsers () return res . json ({ result : true , data : result }) } catch ( e ) { return res . status ( 400 ). json ({ result : false , data : e }) } }) . post < User > ( async ( req , res ) => { try { const result = await createUser () return res . json ({ result : true , data : result }) } catch ( e ) { return res . status ( 400 ). json ({ result : false , data : e }) } }) . prepare ()
Enter fullscreen mode Exit fullscreen mode // pages/api/users/[id].ts export default handleMethods ({ id : string }) . get < Array < User >> ( async ( req , res ) => { try { // you can access query.id type safely. const result = await findUsers ({ id : req . query . id }) return res . json ({ result : true , data : result }) } catch ( e ) { return res . status ( 400 ). json ({ result : false , data : e }) } }) . prepare ()
Enter fullscreen mode Exit fullscreen mode
Top comments (4)
This is good,
But don't you think you have made very simple thing into a very complicated one?
Next.js NextApiHandler can define only one response body type.
So if a route has multiple methods and response body types, you will use the Type Assertion and you will need to write many codes more.
This utility method can decrease codes a little.
Nice article, btw you have a little typo in your Array types :)
I missed it. Thank you ;)