I want to create a standard type for a function that'll always receive the same type of params, but the ReturnType of the function will depend on the function's inferrable body.
So far I have these two ways to get the job done partially:
I can type the function's params, but the response doesn't get inferred anymore.
type Handler = (req: NextApiRequest, res: NextApiResponse) => unknown
const getExamples: Handler = async (req, res) => {
// req gets typed as 'NextApiRequest'
return db.example.findMany()
}
// ReturnType gets typed as unknown
export type GetExamplesResponse = ReturnType<typeof getExamples>
I can also infer the function's ReturnType, but the params are now implicitly any.
const getExamples = async (req, res) => {
// req is implicitly "any"
return db.example.findMany()
}
// ReturnType gets typed as Promise<Example[]>
export type GetExamplesResponse = ReturnType<typeof getExamples>
Is there a way to combine the best of both approaches into a single generic type/interface that'll let my IDE know the types of req & res and at the same time allow the ReturnType to be inferrable?
Here's a typescript playground example without the imported types
CodePudding user response:
If you specify the function type explicitly const getExamples: Handler - it will override the inferred type. Instead you could provide the type for
the rest parameter:
type Params = [NextApiRequest, NextApiResponse]
const ex1 = async (...[req, res]: Params) => req.foo // Promise<string>
const ex2 = async (...[req, res]: Params) => res.bar // Promise<number>
Other option would be using "factory" function:
const createHandler = <T>(handler: (req: NextApiRequest, res: NextApiResponse) => T) => handler;
// (req: NextApiRequest, res: NextApiResponse) => Promise<string>
const ex1 = createHandler(async (req, res) => {
return req.foo
})
// (req: NextApiRequest, res: NextApiResponse) => Promise<number>
const ex2 = createHandler(async (req, res) => {
return res.bar
})


