Closed kimsagro1 closed 4 years ago
Issue-Label Bot is automatically applying the label question
to this issue, with a confidence of 0.75. Please mark this comment with :thumbsup: or :thumbsdown: to give our bot feedback!
Links: app homepage, dashboard and code for this bot.
It should work like this. if you configure the middlewares correctly. E. g. classValidator requires a bodyType
.
You could even write it as:
const wrapper = compose(
// add cors headers last so even error responses from the
// errorHandler middleware have cors headers applied
cors(),
errorHandler(),
jsonSerializer(),
classValidator(),
)
If it is not working, I would need to see the actual error and more context.
So the error I'm getting is
Argument of type '<Event_1 extends { headers: { [name: string]: string; }; httpMethod: string; }>(handler: PromiseHandler<Event_1, APIGatewayProxyResult>) => (event: Event_1, context: Context) => Promise<...>' is not assignable to parameter of type '(x: unknown) => unknown'.
Types of parameters 'handler' and 'x' are incompatible.
Type 'unknown' is not assignable to type 'PromiseHandler<{ headers: { [name: string]: string; }; httpMethod: string; }, APIGatewayProxyResult>'
I have created a codesandbox that demonstrates the issue
Thanks! This is related to TypeScript not being able to infer some generic types yet. I've changed the types in the newest versions of packages so that the error will not appear, as generics are only needed to cover some rather obscure cases of usage. I will post a list of new versions once all have been published.
Here's the list of updated versions: "@lambda-middleware/class-validator": "^2.0.0", "@lambda-middleware/compose": "^1.1.0", "@lambda-middleware/cors": "^2.0.0", "@lambda-middleware/json-serializer": "^2.0.0", "@lambda-middleware/jwt-auth": "^1.0.2", "@lambda-middleware/http-error-handler": "^2.0.0",
@dbartholomae This is still not working for me. Now I get the error
Argument of type '<R>(handler: PromiseHandler<WithBody<APIGatewayProxyEvent, NameBody>, R>) => (event: APIGatewayProxyEvent, context: Context) => Promise<...>' is not assignable to parameter of type '(handler: PromiseHandler<WithBody<APIGatewayProxyEvent, NameBody>, unknown>) => PromiseHandler<APIGatewayProxyEvent, { ...; } | ... 1 more ... | undefined>'.
Call signature return types '(event: APIGatewayProxyEvent, context: Context) => Promise<unknown>' and 'PromiseHandler<APIGatewayProxyEvent, { [key: string]: JSONPrimitive; } | JSONObject[] | undefined>' are incompatible.
Type 'Promise<unknown>' is not assignable to type 'Promise<{ [key: string]: JSONPrimitive; } | JSONObject[] | undefined>'.
Type 'unknown' is not assignable to type '{ [key: string]: JSONPrimitive; } | JSONObject[] | undefined'.
Type 'unknown' is not assignable to type 'JSONObject[]'.ts(2345)
I have created a codesandbox that demonstrates the issue
I did some investigation and I think it only occurs when you set "strict": true
in your tsconfig.json
Thanks, I'll adapt it so it also work in strict mode next week :)
Unfortunately, TypeScript does not possess the capabilities to resolve the generics in a compose function in strict mode (see https://github.com/microsoft/TypeScript/issues/29904 point 1). I've added composeHandler
as a helper function that can be used to achieve full type safety.
@dbartholomae composeHandler
is not working for me under specific scenarios
Manual function chaining works with no compilation errors
const wrapper_manual =
cors()(
errorHandler()(
jsonSerializer()(
bodyParser()(
zodValidator(nameSchema)(
handler
)
)
)
)
);
composeHandler
works as long as I invoke the second last function with the handler
const composeHandlerWrapper = composeHandler(
cors(),
errorHandler(),
jsonSerializer(),
bodyParser(),
zodValidator(nameSchema)(handler)
)
composeHandler
causes a compilation error when invoked as per the documentation
const composeHandlerWrapper = composeHandler(
cors(),
errorHandler(),
jsonSerializer(),
bodyParser(),
zodValidator(nameSchema),
handler
)
Argument of type '<TEvent extends APIGatewayProxyEvent, TResult>(handler: PromiseHandler<WithBody<TEvent, object>, TResult>) => (event: TEvent, context: Context) => Promise<TResult>' is not assignable to parameter of type '(x: unknown) => PromiseHandler<APIGatewayProxyEvent, { [key: string]: JSONPrimitive; } | JSONObject[] | undefined>'.
Types of parameters 'handler' and 'x' are incompatible.
Type 'unknown' is not assignable to type 'PromiseHandler<WithBody<APIGatewayProxyEvent, object>, { [key: string]: JSONPrimitive; } | JSONObject[] | undefined>'
I have created a codesandbox that demonstrates the issue
That's the same problem - unfortunately currently not fully solvable in TypeScript. I would recommend going with the solution where the handler is wrapped for now until TypeScript has better inference for generics.
I'm trying to expose a wrapper function so that all my lambda handlers have the same middleware applied to them.
However I'm struggling to get the type information to line up.
Is it possible to chain these middlewares like this as you can do using middy?