diff --git a/src/types.ts b/src/types.ts index 8dad4c1e5..9780c2fb4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1034,6 +1034,23 @@ type MergeFlattenMacroResponse = { ? B[K] : never } + +type UnionKeys = T extends unknown ? keyof T : never + +type UnionValue = T extends unknown + ? K extends keyof T + ? T[K] + : never + : never + +type MergeObjectUnion = [T] extends [object] + ? Prettify< + { + [K in UnionKeys]: UnionValue + } + > + : T + type UnionMacroContext = UnionToIntersect<{ [K in Exclude]: A[K] }> & { @@ -1054,7 +1071,12 @@ export type MacroToContext< R > extends infer A ? { - [K in Exclude]: UnionToIntersect + [K in Exclude< + keyof A, + 'return' + >]: K extends 'resolve' + ? MergeObjectUnion + : UnionToIntersect } & Prettify<{ // @ts-ignore return: FlattenMacroResponse diff --git a/test/types/macro.ts b/test/types/macro.ts index 8575f259d..83dee92c1 100644 --- a/test/types/macro.ts +++ b/test/types/macro.ts @@ -231,6 +231,44 @@ import { expectTypeOf } from 'expect-type' ) } +// resolve union of object shapes preserves shared context +{ + const plugin = new Elysia({ name: 'plugin' }).macro({ + withUser: { + resolve() { + if (Math.random() > 0.5) + return { + user: { + id: 'a' + } + } + + return { + user: { + id: 'b' + }, + admin: true + } + } + } + }) + + new Elysia() + .use(plugin) + .get( + '/', + ({ user, admin }) => { + expectTypeOf(user).toEqualTypeOf<{ id: string }>() + expectTypeOf(admin).toEqualTypeOf() + + return user.id + }, + { + withUser: true + } + ) +} + // resolve with custom status { const app = new Elysia()