Type error when adding headers to validation schema typescript
sterzhakov opened this issue · 4 comments
Hi, I really like your library!
I tried to modify your typescript example for validating request headers but I got type errors
import Joi from 'joi'
import express from 'express'
import {
ContainerTypes,
// Use this as a replacement for express.Request
ValidatedRequest,
// Extend from this to define a valid schema type/interface
ValidatedRequestSchema,
// Creates a validator that generates middlewares
createValidator
} from 'express-joi-validation'
const app = express()
const validator = createValidator()
const querySchema = Joi.object({
name: Joi.string().required()
})
const headersSchema = Joi.object({
'user-agent': Joi.string().required()
})
interface HelloRequestSchema extends ValidatedRequestSchema {
[ContainerTypes.Query]: {
name: string
},
[ContainerTypes.Headers]: {
'user-agent': string,
}
}
app.get(
'/hello',
validator.query(querySchema),
validator.headers(headersSchema),
(req: ValidatedRequest<HelloRequestSchema>, res) => {
// Woohoo, type safety and intellisense for req.query!
res.end(`Hello ${req.query.name}!`)
}
)
ts error:
No overload matches this call.
The last overload gave the following error.
Argument of type '(req: ValidatedRequest<HelloRequestSchema>, res: Response<any, Record<string, any>, number>) => void' is not assignable to parameter of type 'RequestHandlerParams<ParamsDictionary, any, any, { name: string; } & ParsedQs, Record<string, any>>'.
Type '(req: ValidatedRequest<HelloRequestSchema>, res: Response<any, Record<string, any>, number>) => void' is not assignable to type 'RequestHandler<ParamsDictionary, any, any, { name: string; } & ParsedQs, Record<string, any>>'.
Types of parameters 'req' and 'req' are incompatible.
Type 'Request<ParamsDictionary, any, any, { name: string; } & ParsedQs, Record<string, any>>' is not assignable to type 'ValidatedRequest<HelloRequestSchema>'.
The types of 'headers['user-agent']' are incompatible between these types.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.ts(2769)
index.d.ts(163, 5): The last overload is declared here.
dependencies
"@types/express": "^4.17.14",
"express": "^4.18.1",
"express-joi-validation": "^5.0.1",
"joi": "^17.6.1"
how can I avoid this?
I've taken a quick look into this. It seems that the Request type from express does not accept a headers generic type, nor does the core http.IncomingRequest
that it extends.
I think a workaround could be to update Request to accept a ReqHeaders
generic type, and then update the req.header() function to return the value for the keys in the new ReqHeaders
generic. We'd also need to update the ValidatedRequest type for this library.
You could then use req.header('user-agent')
to get the string with correct typings based on validations (I think!) and it'd fix the compilation issue.
BTW, I guess in the meantime you can remove the headers for the ValidatedRequestSchema
like so:
interface HelloRequestSchema extends ValidatedRequestSchema {
[ContainerTypes.Query]: {
name: string
}
}
And do something similar to this in the request handler:
(req: ValidatedRequest<HelloRequestSchema>, res) => {
const headers = req.headers as { 'user-agent': string }
res.end(`Hello ${req.query.name}!`)
}
The validation will still run.
I found another server solution for my project which have better typescript support, fastify + zod.
Thanks for your quick reply 👍
Nice. Fastify is the way to go these days for sure.