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 ;)