typera
typera copied to clipboard
`Parser.query` order affects type conversion
When using typera-express
with io-ts
, we encountered a situation where the order in which Parser.query
is applied seems to affect the type conversion of query parameters.
For reference, we are using the following types for the query parameters:
const Category = t.string; // Represents a category as a string
const PagingParams = t.type({
page: IntFromString, // Page number, expected to be converted to a number
itemsPerPage: IntFromString // Items per page, also expected to be converted to a number
});
Below are examples of three patterns that demonstrate the issue:
-
Pattern 1 (Working as expected): Using
t.intersection
to combinecategory
andPagingParams
works as intended. Bothpage
anditemsPerPage
are correctly converted to numbers.
const getWithIntersection = route
.get('/test1')
.use(Parser.query(t.intersection([t.type({ category: t.string }), PagingParams])))
.handler(async req => {
console.log(req.query); // { category: 'books', page: 1, itemsPerPage: 10 } Correct conversion
return Response.ok(req.query);
});
-
Pattern 2 (Working as expected): Applying
Parser.query
separately, first withcategory
and then withPagingParams
, also results in correct conversion. Bothpage
anditemsPerPage
are properly handled as numbers.
const getWithSeparateUse = route
.get('/test2')
.use(Parser.query(t.type({ category: t.string })))
.use(Parser.query(PagingParams))
.handler(async req => {
console.log(req.query); // { category: 'books', page: 1, itemsPerPage: 10 } Correct conversion
return Response.ok(req.query);
});
-
Pattern 3 (Issue): However, when
Parser.query(PagingParams)
is placed beforeParser.query(t.type({ category: t.string }))
, thepage
anditemsPerPage
parameters remain as strings instead of being converted to numbers. This behavior is unexpected, given that both patterns should logically result in the same output.
const getWithSeparateUse2 = route
.get('/test3')
.use(Parser.query(PagingParams)) // Applied first
.use(Parser.query(t.type({ category: t.string })))
.handler(async req => {
console.log(req.query); // { category: 'books', page: '1', itemsPerPage: '10' } page and itemsPerPage remain strings
return Response.ok(req.query);
});
Expected Behavior:
In all cases, page
and itemsPerPage
should be converted to numbers, as they are defined using IntFromString
. However, the current behavior suggests that the order of applying Parser.query
influences whether the conversion happens correctly, which can be surprising for developers. Since both the approach used in test2
and test3
are valid and commonly used, it would be more intuitive if they behaved consistently, regardless of the order in which the parsers are applied.