Skip to content

Commit

Permalink
fix(types): Calculate Context<Env> type for each handler (#3587)
Browse files Browse the repository at this point in the history
  • Loading branch information
sushichan044 committed Nov 28, 2024
1 parent a15bec3 commit 173a2cf
Show file tree
Hide file tree
Showing 4 changed files with 380 additions and 260 deletions.
107 changes: 91 additions & 16 deletions src/helper/factory/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,22 +231,97 @@ describe('createHandler', () => {
describe('Types - Context Env with Multiple Middlewares', () => {
const factory = createFactory()

const mw1 = createMiddleware<{ Variables: { foo: string } }>(async (c, next) => {
c.set('foo', 'bar')
await next()
})

const mw2 = createMiddleware<{ Variables: { bar: number } }>(async (c, next) => {
c.set('bar', 1)
await next()
})

it('Should set the correct type for context from multiple middlewares', () => {
factory.createHandlers(mw1, mw2, (c) => {
expectTypeOf(c.var.foo).toEqualTypeOf<string>()
expectTypeOf(c.var.bar).toEqualTypeOf<number>()

return c.json({ foo: c.var.foo, bar: c.var.bar })
const mw1 = createMiddleware<
{ Variables: { foo1: string } },
string,
{ out: { query: { bar1: number } } }
>(async () => {})
const mw2 = createMiddleware<
{ Variables: { foo2: string } },
string,
{ out: { query: { bar2: number } } }
>(async () => {})
const mw3 = createMiddleware<
{ Variables: { foo3: string } },
string,
{ out: { query: { bar3: number } } }
>(async () => {})
const mw4 = createMiddleware<
{ Variables: { foo4: string } },
string,
{ out: { query: { bar4: number } } }
>(async () => {})
const mw5 = createMiddleware<
{ Variables: { foo5: string } },
string,
{ out: { query: { bar5: number } } }
>(async () => {})
const mw6 = createMiddleware<
{ Variables: { foo6: string } },
string,
{ out: { query: { bar6: number } } }
>(async () => {})
const mw7 = createMiddleware<
{ Variables: { foo7: string } },
string,
{ out: { query: { bar7: number } } }
>(async () => {})
const mw8 = createMiddleware<
{ Variables: { foo8: string } },
string,
{ out: { query: { bar8: number } } }
>(async () => {})
const mw9 = createMiddleware<
{ Variables: { foo9: string } },
string,
{ out: { query: { bar9: number } } }
>(async () => {})

it('Should not throw type error', () => {
factory.createHandlers(
mw1,
mw2,
mw3,
mw4,
mw5,
mw6,
mw7,
mw8,
async (c) => {
expectTypeOf(c.var.foo1).toEqualTypeOf<string>()
expectTypeOf(c.var.foo2).toEqualTypeOf<string>()
expectTypeOf(c.var.foo3).toEqualTypeOf<string>()
expectTypeOf(c.var.foo4).toEqualTypeOf<string>()
expectTypeOf(c.var.foo5).toEqualTypeOf<string>()
expectTypeOf(c.var.foo6).toEqualTypeOf<string>()
expectTypeOf(c.var.foo7).toEqualTypeOf<string>()
expectTypeOf(c.var.foo8).toEqualTypeOf<string>()
},
(c) => c.json(0)
)

factory.createHandlers(mw1, mw2, mw3, mw4, mw5, mw6, mw7, mw8, mw9, (c) => {
expectTypeOf(c.var.foo1).toEqualTypeOf<string>()
expectTypeOf(c.var.foo2).toEqualTypeOf<string>()
expectTypeOf(c.var.foo3).toEqualTypeOf<string>()
expectTypeOf(c.var.foo4).toEqualTypeOf<string>()
expectTypeOf(c.var.foo5).toEqualTypeOf<string>()
expectTypeOf(c.var.foo6).toEqualTypeOf<string>()
expectTypeOf(c.var.foo7).toEqualTypeOf<string>()
expectTypeOf(c.var.foo8).toEqualTypeOf<string>()
expectTypeOf(c.var.foo9).toEqualTypeOf<string>()

return c.json({
foo1: c.get('foo1'),
foo2: c.get('foo2'),
foo3: c.get('foo3'),
foo4: c.get('foo4'),
foo5: c.get('foo5'),
foo6: c.get('foo6'),
foo7: c.get('foo7'),
foo8: c.get('foo8'),
foo9: c.get('foo9'),
})
})
})
})
Expand Down
72 changes: 36 additions & 36 deletions src/helper/factory/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
I3 extends Input = I & I2,
R extends HandlerResponse<any> = any,
E2 extends Env = E,
E3 extends Env = E,
E3 extends Env = IntersectNonAnyTypes<[E, E2]>,
E4 extends Env = IntersectNonAnyTypes<[E, E2, E3]>
>(
handler1: H<E2, P, I, R>,
Expand All @@ -56,8 +56,8 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
I4 extends Input = I & I2 & I3,
R extends HandlerResponse<any> = any,
E2 extends Env = E,
E3 extends Env = E,
E4 extends Env = E,
E3 extends Env = IntersectNonAnyTypes<[E, E2]>,
E4 extends Env = IntersectNonAnyTypes<[E, E2, E3]>,
E5 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4]>
>(
handler1: H<E2, P, I, R>,
Expand All @@ -75,9 +75,9 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
I5 extends Input = I & I2 & I3 & I4,
R extends HandlerResponse<any> = any,
E2 extends Env = E,
E3 extends Env = E,
E4 extends Env = E,
E5 extends Env = E,
E3 extends Env = IntersectNonAnyTypes<[E, E2]>,
E4 extends Env = IntersectNonAnyTypes<[E, E2, E3]>,
E5 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4]>,
E6 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5]>
>(
handler1: H<E2, P, I, R>,
Expand All @@ -97,10 +97,10 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
I6 extends Input = I & I2 & I3 & I4 & I5,
R extends HandlerResponse<any> = any,
E2 extends Env = E,
E3 extends Env = E,
E4 extends Env = E,
E5 extends Env = E,
E6 extends Env = E,
E3 extends Env = IntersectNonAnyTypes<[E, E2]>,
E4 extends Env = IntersectNonAnyTypes<[E, E2, E3]>,
E5 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4]>,
E6 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5]>,
E7 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6]>
>(
handler1: H<E2, P, I, R>,
Expand Down Expand Up @@ -129,11 +129,11 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
I7 extends Input = I & I2 & I3 & I4 & I5 & I6,
R extends HandlerResponse<any> = any,
E2 extends Env = E,
E3 extends Env = E,
E4 extends Env = E,
E5 extends Env = E,
E6 extends Env = E,
E7 extends Env = E,
E3 extends Env = IntersectNonAnyTypes<[E, E2]>,
E4 extends Env = IntersectNonAnyTypes<[E, E2, E3]>,
E5 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4]>,
E6 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5]>,
E7 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6]>,
E8 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7]>
>(
handler1: H<E2, P, I, R>,
Expand Down Expand Up @@ -165,12 +165,12 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
I8 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7,
R extends HandlerResponse<any> = any,
E2 extends Env = E,
E3 extends Env = E,
E4 extends Env = E,
E5 extends Env = E,
E6 extends Env = E,
E7 extends Env = E,
E8 extends Env = E,
E3 extends Env = IntersectNonAnyTypes<[E, E2]>,
E4 extends Env = IntersectNonAnyTypes<[E, E2, E3]>,
E5 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4]>,
E6 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5]>,
E7 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6]>,
E8 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7]>,
E9 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8]>
>(
handler1: H<E2, P, I, R>,
Expand Down Expand Up @@ -205,13 +205,13 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
I9 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7 & I8,
R extends HandlerResponse<any> = any,
E2 extends Env = E,
E3 extends Env = E,
E4 extends Env = E,
E5 extends Env = E,
E6 extends Env = E,
E7 extends Env = E,
E8 extends Env = E,
E9 extends Env = E,
E3 extends Env = IntersectNonAnyTypes<[E, E2]>,
E4 extends Env = IntersectNonAnyTypes<[E, E2, E3]>,
E5 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4]>,
E6 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5]>,
E7 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6]>,
E8 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7]>,
E9 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8]>,
E10 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8, E9]>
>(
handler1: H<E2, P, I, R>,
Expand Down Expand Up @@ -249,14 +249,14 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
I10 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7 & I8 & I9,
R extends HandlerResponse<any> = any,
E2 extends Env = E,
E3 extends Env = E,
E4 extends Env = E,
E5 extends Env = E,
E6 extends Env = E,
E7 extends Env = E,
E8 extends Env = E,
E9 extends Env = E,
E10 extends Env = E,
E3 extends Env = IntersectNonAnyTypes<[E, E2]>,
E4 extends Env = IntersectNonAnyTypes<[E, E2, E3]>,
E5 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4]>,
E6 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5]>,
E7 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6]>,
E8 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7]>,
E9 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8]>,
E10 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8, E9]>,
E11 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8, E9, E10]>
>(
handler1: H<E2, P, I, R>,
Expand Down
45 changes: 45 additions & 0 deletions src/types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,28 @@ describe('c.var with chaining - test only types', () => {
return c.json(0)
})

new Hono().get(
mw1,
mw2,
mw3,
mw4,
mw5,
mw6,
mw7,
mw8,
(c) => {
expectTypeOf(c.var.foo1).toEqualTypeOf<string>()
expectTypeOf(c.var.foo2).toEqualTypeOf<string>()
expectTypeOf(c.var.foo3).toEqualTypeOf<string>()
expectTypeOf(c.var.foo4).toEqualTypeOf<string>()
expectTypeOf(c.var.foo5).toEqualTypeOf<string>()
expectTypeOf(c.var.foo6).toEqualTypeOf<string>()
expectTypeOf(c.var.foo7).toEqualTypeOf<string>()
expectTypeOf(c.var.foo8).toEqualTypeOf<string>()
},
(c) => c.json(0)
)

new Hono().get(mw1, mw2, mw3, mw4, mw5, mw6, mw7, mw8, mw9, (c) => {
expectTypeOf(c.req.valid('query')).toMatchTypeOf<{
bar1: number
Expand All @@ -1314,6 +1336,29 @@ describe('c.var with chaining - test only types', () => {
return c.json(0)
})

new Hono().get(
'/',
mw1,
mw2,
mw3,
mw4,
mw5,
mw6,
mw7,
mw8,
(c) => {
expectTypeOf(c.var.foo1).toEqualTypeOf<string>()
expectTypeOf(c.var.foo2).toEqualTypeOf<string>()
expectTypeOf(c.var.foo3).toEqualTypeOf<string>()
expectTypeOf(c.var.foo4).toEqualTypeOf<string>()
expectTypeOf(c.var.foo5).toEqualTypeOf<string>()
expectTypeOf(c.var.foo6).toEqualTypeOf<string>()
expectTypeOf(c.var.foo7).toEqualTypeOf<string>()
expectTypeOf(c.var.foo8).toEqualTypeOf<string>()
},
(c) => c.json(0)
)

new Hono().get('/', mw1, mw2, mw3, mw4, mw5, mw6, mw7, mw8, mw9, (c) => {
expectTypeOf(c.req.valid('query')).toMatchTypeOf<{
bar1: number
Expand Down
Loading

0 comments on commit 173a2cf

Please sign in to comment.