0
0
mirror of https://github.com/honojs/hono.git synced 2024-11-21 10:08:58 +01:00

feat(helper/factory): Calculate Context<Env> 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
This commit is contained in:
Kentaro Suzuki 2024-11-15 05:13:59 +09:00 committed by GitHub
parent 1e8ebe9f04
commit a15bec3275
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 203 additions and 107 deletions

View File

@ -227,6 +227,29 @@ describe('createHandler', () => {
expectTypeOf(routes).toEqualTypeOf<Expected>()
})
})
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 })
})
})
})
})
describe('createApp', () => {

View File

@ -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<E extends Env = Env> = (app: Hono<E>) => void
export interface CreateHandlersInterface<E extends Env, P extends string> {
<I extends Input = {}, R extends HandlerResponse<any> = any>(handler1: H<E, P, I, R>): [
H<E, P, I, R>
]
<I extends Input = {}, R extends HandlerResponse<any> = any, E2 extends Env = E>(
handler1: H<E2, P, I, R>
): [H<E2, P, I, R>]
// handler x2
<I extends Input = {}, I2 extends Input = I, R extends HandlerResponse<any> = any>(
handler1: H<E, P, I, R>,
handler2: H<E, P, I2, R>
): [H<E, P, I, R>, H<E, P, I2, R>]
<
I extends Input = {},
I2 extends Input = I,
R extends HandlerResponse<any> = any,
E2 extends Env = E,
E3 extends Env = IntersectNonAnyTypes<[E, E2]>
>(
handler1: H<E2, P, I, R>,
handler2: H<E3, P, I2, R>
): [H<E2, P, I, R>, H<E3, P, I2, R>]
// handler x3
<
I extends Input = {},
I2 extends Input = I,
I3 extends Input = I & I2,
R extends HandlerResponse<any> = any
R extends HandlerResponse<any> = any,
E2 extends Env = E,
E3 extends Env = E,
E4 extends Env = IntersectNonAnyTypes<[E, E2, E3]>
>(
handler1: H<E, P, I, R>,
handler2: H<E, P, I2, R>,
handler3: H<E, P, I3, R>
): [H<E, P, I, R>, H<E, P, I2, R>, H<E, P, I3, R>]
handler1: H<E2, P, I, R>,
handler2: H<E3, P, I2, R>,
handler3: H<E4, P, I3, R>
): [H<E2, P, I, R>, H<E3, P, I2, R>, H<E4, P, I3, R>]
// handler x4
<
@ -37,13 +54,17 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
I2 extends Input = I,
I3 extends Input = I & I2,
I4 extends Input = I & I2 & I3,
R extends HandlerResponse<any> = any
R extends HandlerResponse<any> = any,
E2 extends Env = E,
E3 extends Env = E,
E4 extends Env = E,
E5 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4]>
>(
handler1: H<E, P, I, R>,
handler2: H<E, P, I2, R>,
handler3: H<E, P, I3, R>,
handler4: H<E, P, I4, R>
): [H<E, P, I, R>, H<E, P, I2, R>, H<E, P, I3, R>, H<E, P, I4, R>]
handler1: H<E2, P, I, R>,
handler2: H<E3, P, I2, R>,
handler3: H<E4, P, I3, R>,
handler4: H<E5, P, I4, R>
): [H<E2, P, I, R>, H<E3, P, I2, R>, H<E4, P, I3, R>, H<E5, P, I4, R>]
// handler x5
<
@ -52,14 +73,19 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
I3 extends Input = I & I2,
I4 extends Input = I & I2 & I3,
I5 extends Input = I & I2 & I3 & I4,
R extends HandlerResponse<any> = any
R extends HandlerResponse<any> = 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<E, P, I, R>,
handler2: H<E, P, I2, R>,
handler3: H<E, P, I3, R>,
handler4: H<E, P, I4, R>,
handler5: H<E, P, I5, R>
): [H<E, P, I, R>, H<E, P, I2, R>, H<E, P, I3, R>, H<E, P, I4, R>, H<E, P, I5, R>]
handler1: H<E2, P, I, R>,
handler2: H<E3, P, I2, R>,
handler3: H<E4, P, I3, R>,
handler4: H<E5, P, I4, R>,
handler5: H<E6, P, I5, R>
): [H<E2, P, I, R>, H<E3, P, I2, R>, H<E4, P, I3, R>, H<E5, P, I4, R>, H<E6, P, I5, R>]
// handler x6
<
@ -69,15 +95,28 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
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> = any
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 = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6]>
>(
handler1: H<E, P, I, R>,
handler2: H<E, P, I2, R>,
handler3: H<E, P, I3, R>,
handler4: H<E, P, I4, R>,
handler5: H<E, P, I5, R>,
handler6: H<E, P, I6, R>
): [H<E, P, I, R>, H<E, P, I2, R>, H<E, P, I3, R>, H<E, P, I4, R>, H<E, P, I5, R>, H<E, P, I6, R>]
handler1: H<E2, P, I, R>,
handler2: H<E3, P, I2, R>,
handler3: H<E4, P, I3, R>,
handler4: H<E5, P, I4, R>,
handler5: H<E6, P, I5, R>,
handler6: H<E7, P, I6, R>
): [
H<E2, P, I, R>,
H<E3, P, I2, R>,
H<E4, P, I3, R>,
H<E5, P, I4, R>,
H<E6, P, I5, R>,
H<E7, P, I6, R>
]
// handler x7
<
@ -88,23 +127,30 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
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> = any
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 = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7]>
>(
handler1: H<E, P, I, R>,
handler2: H<E, P, I2, R>,
handler3: H<E, P, I3, R>,
handler4: H<E, P, I4, R>,
handler5: H<E, P, I5, R>,
handler6: H<E, P, I6, R>,
handler7: H<E, P, I7, R>
handler1: H<E2, P, I, R>,
handler2: H<E3, P, I2, R>,
handler3: H<E4, P, I3, R>,
handler4: H<E5, P, I4, R>,
handler5: H<E6, P, I5, R>,
handler6: H<E7, P, I6, R>,
handler7: H<E8, P, I7, R>
): [
H<E, P, I, R>,
H<E, P, I2, R>,
H<E, P, I3, R>,
H<E, P, I4, R>,
H<E, P, I5, R>,
H<E, P, I6, R>,
H<E, P, I7, R>
H<E2, P, I, R>,
H<E3, P, I2, R>,
H<E4, P, I3, R>,
H<E5, P, I4, R>,
H<E6, P, I5, R>,
H<E7, P, I6, R>,
H<E8, P, I7, R>
]
// handler x8
@ -117,25 +163,33 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
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> = any
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 = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8]>
>(
handler1: H<E, P, I, R>,
handler2: H<E, P, I2, R>,
handler3: H<E, P, I3, R>,
handler4: H<E, P, I4, R>,
handler5: H<E, P, I5, R>,
handler6: H<E, P, I6, R>,
handler7: H<E, P, I7, R>,
handler8: H<E, P, I8, R>
handler1: H<E2, P, I, R>,
handler2: H<E3, P, I2, R>,
handler3: H<E4, P, I3, R>,
handler4: H<E5, P, I4, R>,
handler5: H<E6, P, I5, R>,
handler6: H<E7, P, I6, R>,
handler7: H<E8, P, I7, R>,
handler8: H<E9, P, I8, R>
): [
H<E, P, I, R>,
H<E, P, I2, R>,
H<E, P, I3, R>,
H<E, P, I4, R>,
H<E, P, I5, R>,
H<E, P, I6, R>,
H<E, P, I7, R>,
H<E, P, I8, R>
H<E2, P, I, R>,
H<E3, P, I2, R>,
H<E4, P, I3, R>,
H<E5, P, I4, R>,
H<E6, P, I5, R>,
H<E7, P, I6, R>,
H<E8, P, I7, R>,
H<E9, P, I8, R>
]
// handler x9
@ -149,27 +203,36 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
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> = any
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 = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8, E9]>
>(
handler1: H<E, P, I, R>,
handler2: H<E, P, I2, R>,
handler3: H<E, P, I3, R>,
handler4: H<E, P, I4, R>,
handler5: H<E, P, I5, R>,
handler6: H<E, P, I6, R>,
handler7: H<E, P, I7, R>,
handler8: H<E, P, I8, R>,
handler9: H<E, P, I9, R>
handler1: H<E2, P, I, R>,
handler2: H<E3, P, I2, R>,
handler3: H<E4, P, I3, R>,
handler4: H<E5, P, I4, R>,
handler5: H<E6, P, I5, R>,
handler6: H<E7, P, I6, R>,
handler7: H<E8, P, I7, R>,
handler8: H<E9, P, I8, R>,
handler9: H<E10, P, I9, R>
): [
H<E, P, I, R>,
H<E, P, I2, R>,
H<E, P, I3, R>,
H<E, P, I4, R>,
H<E, P, I5, R>,
H<E, P, I6, R>,
H<E, P, I7, R>,
H<E, P, I8, R>,
H<E, P, I9, R>
H<E2, P, I, R>,
H<E3, P, I2, R>,
H<E4, P, I3, R>,
H<E5, P, I4, R>,
H<E6, P, I5, R>,
H<E7, P, I6, R>,
H<E8, P, I7, R>,
H<E9, P, I8, R>,
H<E10, P, I9, R>
]
// handler x10
@ -184,29 +247,39 @@ export interface CreateHandlersInterface<E extends Env, P extends string> {
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> = any
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,
E11 extends Env = IntersectNonAnyTypes<[E, E2, E3, E4, E5, E6, E7, E8, E9, E10]>
>(
handler1: H<E, P, I, R>,
handler2: H<E, P, I2, R>,
handler3: H<E, P, I3, R>,
handler4: H<E, P, I4, R>,
handler5: H<E, P, I5, R>,
handler6: H<E, P, I6, R>,
handler7: H<E, P, I7, R>,
handler8: H<E, P, I8, R>,
handler9: H<E, P, I9, R>,
handler10: H<E, P, I10, R>
handler1: H<E2, P, I, R>,
handler2: H<E3, P, I2, R>,
handler3: H<E4, P, I3, R>,
handler4: H<E5, P, I4, R>,
handler5: H<E6, P, I5, R>,
handler6: H<E7, P, I6, R>,
handler7: H<E8, P, I7, R>,
handler8: H<E9, P, I8, R>,
handler9: H<E10, P, I9, R>,
handler10: H<E11, P, I10, R>
): [
H<E, P, I, R>,
H<E, P, I2, R>,
H<E, P, I3, R>,
H<E, P, I4, R>,
H<E, P, I5, R>,
H<E, P, I6, R>,
H<E, P, I7, R>,
H<E, P, I8, R>,
H<E, P, I9, R>,
H<E, P, I10, R>
H<E2, P, I, R>,
H<E3, P, I2, R>,
H<E4, P, I3, R>,
H<E5, P, I4, R>,
H<E6, P, I5, R>,
H<E7, P, I6, R>,
H<E8, P, I7, R>,
H<E9, P, I8, R>,
H<E10, P, I9, R>,
H<E11, P, I10, R>
]
}

View File

@ -1985,7 +1985,7 @@ export type ExtractSchema<T> = UnionToIntersection<
>
type EnvOrEmpty<T> = T extends Env ? (Env extends T ? {} : T) : T
type IntersectNonAnyTypes<T extends any[]> = T extends [infer Head, ...infer Rest]
export type IntersectNonAnyTypes<T extends any[]> = T extends [infer Head, ...infer Rest]
? IfAnyThenEmptyObject<EnvOrEmpty<Head>> & IntersectNonAnyTypes<Rest>
: {}