From a15bec32759dd735e32121b54f279e989c7a956e Mon Sep 17 00:00:00 2001 From: Kentaro Suzuki Date: Fri, 15 Nov 2024 05:13:59 +0900 Subject: [PATCH] feat(helper/factory): Calculate Context Type in createHandlers (#3670) * chore(types): export IntersectNonAnyTypes (#3467) * feat(helper/factory): Calculate context env type in createHandlers (#3467) * feat(factory): test context env type in createHandlers --- src/helper/factory/index.test.ts | 23 +++ src/helper/factory/index.ts | 285 +++++++++++++++++++------------ src/types.ts | 2 +- 3 files changed, 203 insertions(+), 107 deletions(-) diff --git a/src/helper/factory/index.test.ts b/src/helper/factory/index.test.ts index f807f7cf..30fe77b6 100644 --- a/src/helper/factory/index.test.ts +++ b/src/helper/factory/index.test.ts @@ -227,6 +227,29 @@ describe('createHandler', () => { expectTypeOf(routes).toEqualTypeOf() }) }) + + 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() + expectTypeOf(c.var.bar).toEqualTypeOf() + + return c.json({ foo: c.var.foo, bar: c.var.bar }) + }) + }) + }) }) describe('createApp', () => { diff --git a/src/helper/factory/index.ts b/src/helper/factory/index.ts index c5fe7a86..49a3cb1c 100644 --- a/src/helper/factory/index.ts +++ b/src/helper/factory/index.ts @@ -5,31 +5,48 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Hono } from '../../hono' -import type { Env, H, HandlerResponse, Input, MiddlewareHandler } from '../../types' +import type { + Env, + H, + HandlerResponse, + Input, + IntersectNonAnyTypes, + MiddlewareHandler, +} from '../../types' type InitApp = (app: Hono) => void export interface CreateHandlersInterface { - = any>(handler1: H): [ - H - ] + = any, E2 extends Env = E>( + handler1: H + ): [H] + // handler x2 - = any>( - handler1: H, - handler2: H - ): [H, H] + < + I extends Input = {}, + I2 extends Input = I, + R extends HandlerResponse = any, + E2 extends Env = E, + E3 extends Env = IntersectNonAnyTypes<[E, E2]> + >( + handler1: H, + handler2: H + ): [H, H] // handler x3 < I extends Input = {}, I2 extends Input = I, I3 extends Input = I & I2, - R extends HandlerResponse = any + R extends HandlerResponse = any, + E2 extends Env = E, + E3 extends Env = E, + E4 extends Env = IntersectNonAnyTypes<[E, E2, E3]> >( - handler1: H, - handler2: H, - handler3: H - ): [H, H, H] + handler1: H, + handler2: H, + handler3: H + ): [H, H, H] // handler x4 < @@ -37,13 +54,17 @@ export interface CreateHandlersInterface { I2 extends Input = I, I3 extends Input = I & I2, I4 extends Input = I & I2 & I3, - R extends HandlerResponse = any + R extends HandlerResponse = any, + E2 extends Env = E, + E3 extends Env = E, + E4 extends Env = E, + E5 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4]> >( - handler1: H, - handler2: H, - handler3: H, - handler4: H - ): [H, H, H, H] + handler1: H, + handler2: H, + handler3: H, + handler4: H + ): [H, H, H, H] // handler x5 < @@ -52,14 +73,19 @@ export interface CreateHandlersInterface { I3 extends Input = I & I2, I4 extends Input = I & I2 & I3, I5 extends Input = I & I2 & I3 & I4, - R extends HandlerResponse = any + R extends HandlerResponse = any, + E2 extends Env = E, + E3 extends Env = E, + E4 extends Env = E, + E5 extends Env = E, + E6 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5]> >( - handler1: H, - handler2: H, - handler3: H, - handler4: H, - handler5: H - ): [H, H, H, H, H] + handler1: H, + handler2: H, + handler3: H, + handler4: H, + handler5: H + ): [H, H, H, H, H] // handler x6 < @@ -69,15 +95,28 @@ export interface CreateHandlersInterface { I4 extends Input = I & I2 & I3, I5 extends Input = I & I2 & I3 & I4, I6 extends Input = I & I2 & I3 & I4 & I5, - R extends HandlerResponse = any + R extends HandlerResponse = any, + E2 extends Env = E, + E3 extends Env = E, + E4 extends Env = E, + E5 extends Env = E, + E6 extends Env = E, + E7 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6]> >( - handler1: H, - handler2: H, - handler3: H, - handler4: H, - handler5: H, - handler6: H - ): [H, H, H, H, H, H] + handler1: H, + handler2: H, + handler3: H, + handler4: H, + handler5: H, + handler6: H + ): [ + H, + H, + H, + H, + H, + H + ] // handler x7 < @@ -88,23 +127,30 @@ export interface CreateHandlersInterface { I5 extends Input = I & I2 & I3 & I4, I6 extends Input = I & I2 & I3 & I4 & I5, I7 extends Input = I & I2 & I3 & I4 & I5 & I6, - R extends HandlerResponse = any + R extends HandlerResponse = 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 = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7]> >( - handler1: H, - handler2: H, - handler3: H, - handler4: H, - handler5: H, - handler6: H, - handler7: H + handler1: H, + handler2: H, + handler3: H, + handler4: H, + handler5: H, + handler6: H, + handler7: H ): [ - H, - H, - H, - H, - H, - H, - H + H, + H, + H, + H, + H, + H, + H ] // handler x8 @@ -117,25 +163,33 @@ export interface CreateHandlersInterface { I6 extends Input = I & I2 & I3 & I4 & I5, I7 extends Input = I & I2 & I3 & I4 & I5 & I6, I8 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7, - R extends HandlerResponse = any + R extends HandlerResponse = 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 = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8]> >( - handler1: H, - handler2: H, - handler3: H, - handler4: H, - handler5: H, - handler6: H, - handler7: H, - handler8: H + handler1: H, + handler2: H, + handler3: H, + handler4: H, + handler5: H, + handler6: H, + handler7: H, + handler8: H ): [ - H, - H, - H, - H, - H, - H, - H, - H + H, + H, + H, + H, + H, + H, + H, + H ] // handler x9 @@ -149,27 +203,36 @@ export interface CreateHandlersInterface { I7 extends Input = I & I2 & I3 & I4 & I5 & I6, I8 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7, I9 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7 & I8, - R extends HandlerResponse = any + R extends HandlerResponse = 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 = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8, E9]> >( - handler1: H, - handler2: H, - handler3: H, - handler4: H, - handler5: H, - handler6: H, - handler7: H, - handler8: H, - handler9: H + handler1: H, + handler2: H, + handler3: H, + handler4: H, + handler5: H, + handler6: H, + handler7: H, + handler8: H, + handler9: H ): [ - H, - H, - H, - H, - H, - H, - H, - H, - H + H, + H, + H, + H, + H, + H, + H, + H, + H ] // handler x10 @@ -184,29 +247,39 @@ export interface CreateHandlersInterface { I8 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7, I9 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7 & I8, I10 extends Input = I & I2 & I3 & I4 & I5 & I6 & I7 & I8 & I9, - R extends HandlerResponse = any + R extends HandlerResponse = 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, + E11 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8, E9, E10]> >( - handler1: H, - handler2: H, - handler3: H, - handler4: H, - handler5: H, - handler6: H, - handler7: H, - handler8: H, - handler9: H, - handler10: H + handler1: H, + handler2: H, + handler3: H, + handler4: H, + handler5: H, + handler6: H, + handler7: H, + handler8: H, + handler9: H, + handler10: H ): [ - H, - H, - H, - H, - H, - H, - H, - H, - H, - H + H, + H, + H, + H, + H, + H, + H, + H, + H, + H ] } diff --git a/src/types.ts b/src/types.ts index 101eed7f..f58f162b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1985,7 +1985,7 @@ export type ExtractSchema = UnionToIntersection< > type EnvOrEmpty = T extends Env ? (Env extends T ? {} : T) : T -type IntersectNonAnyTypes = T extends [infer Head, ...infer Rest] +export type IntersectNonAnyTypes = T extends [infer Head, ...infer Rest] ? IfAnyThenEmptyObject> & IntersectNonAnyTypes : {}