From b3a168229cfdab92065a40e4ad186943392a3601 Mon Sep 17 00:00:00 2001 From: unnoq Date: Sat, 15 Mar 2025 08:34:08 +0700 Subject: [PATCH 1/4] ContextExtendsGuard --- packages/server/src/builder-variants.test-d.ts | 12 ++++++------ packages/server/src/builder.test-d.ts | 2 +- packages/server/src/context.ts | 2 +- packages/server/src/implementer-procedure.test-d.ts | 4 ++-- packages/server/src/implementer-variants.test-d.ts | 2 +- packages/server/src/implementer.test-d.ts | 2 +- packages/server/src/middleware-decorated.test-d.ts | 6 +++--- packages/server/src/procedure-decorated.test-d.ts | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/server/src/builder-variants.test-d.ts b/packages/server/src/builder-variants.test-d.ts index 3109973e4..8108f8e72 100644 --- a/packages/server/src/builder-variants.test-d.ts +++ b/packages/server/src/builder-variants.test-d.ts @@ -108,7 +108,7 @@ describe('BuilderWithMiddlewares', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(builder.use(mid)).toEqualTypeOf< BuilderWithMiddlewares< @@ -368,7 +368,7 @@ describe('ProcedureBuilder', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(builder.use(mid)).toEqualTypeOf< ProcedureBuilder< @@ -610,7 +610,7 @@ describe('ProcedureBuilderWithInput', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(builder.use(mid)).toEqualTypeOf< ProcedureBuilderWithInput< @@ -799,7 +799,7 @@ describe('ProcedureBuilderWithOutput', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(builder.use(mid)).toEqualTypeOf< ProcedureBuilderWithOutput< @@ -1028,7 +1028,7 @@ describe('ProcedureBuilderWithInputOutput', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(builder.use(mid)).toEqualTypeOf< ProcedureBuilderWithInputOutput< @@ -1173,7 +1173,7 @@ describe('RouterBuilder', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(builder.use(mid)).toEqualTypeOf< RouterBuilder< diff --git a/packages/server/src/builder.test-d.ts b/packages/server/src/builder.test-d.ts index 042f22b34..bc256be52 100644 --- a/packages/server/src/builder.test-d.ts +++ b/packages/server/src/builder.test-d.ts @@ -298,7 +298,7 @@ describe('Builder', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(builder.use(mid)).toEqualTypeOf< BuilderWithMiddlewares< diff --git a/packages/server/src/context.ts b/packages/server/src/context.ts index 3f444e4e1..3826c73f9 100644 --- a/packages/server/src/context.ts +++ b/packages/server/src/context.ts @@ -15,4 +15,4 @@ export function mergeCurrentContext( return { ...context, ...other } } -export type ContextExtendsGuard = T extends T & U ? unknown : never +export type ContextExtendsGuard = T extends U ? unknown : never diff --git a/packages/server/src/implementer-procedure.test-d.ts b/packages/server/src/implementer-procedure.test-d.ts index ec7d3b7dd..ea86ed7d3 100644 --- a/packages/server/src/implementer-procedure.test-d.ts +++ b/packages/server/src/implementer-procedure.test-d.ts @@ -140,7 +140,7 @@ describe('ImplementedProcedure', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(implemented.use(mid)).toEqualTypeOf< ImplementedProcedure< @@ -322,7 +322,7 @@ describe('ProcedureImplementer', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(builder.use(mid)).toEqualTypeOf< ProcedureImplementer< diff --git a/packages/server/src/implementer-variants.test-d.ts b/packages/server/src/implementer-variants.test-d.ts index 9e317fbd9..27c756180 100644 --- a/packages/server/src/implementer-variants.test-d.ts +++ b/packages/server/src/implementer-variants.test-d.ts @@ -56,7 +56,7 @@ describe('ImplementerWithMiddlewares', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(implementer.use(mid)).toEqualTypeOf< ImplementerInternalWithMiddlewares< diff --git a/packages/server/src/implementer.test-d.ts b/packages/server/src/implementer.test-d.ts index 8c2c547ad..daa00140b 100644 --- a/packages/server/src/implementer.test-d.ts +++ b/packages/server/src/implementer.test-d.ts @@ -125,7 +125,7 @@ describe('Implementer', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, unknown, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(implementer.use(mid)).toEqualTypeOf< ImplementerInternalWithMiddlewares< diff --git a/packages/server/src/middleware-decorated.test-d.ts b/packages/server/src/middleware-decorated.test-d.ts index bea5ad86f..34d83a178 100644 --- a/packages/server/src/middleware-decorated.test-d.ts +++ b/packages/server/src/middleware-decorated.test-d.ts @@ -132,11 +132,11 @@ describe('DecoratedMiddleware', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(decorated.concat(mid)).toEqualTypeOf< DecoratedMiddleware< - CurrentContext & Omit<{ cacheable?: boolean }, 'db' | 'auth' | 'extra'>, + CurrentContext & Omit<{ cacheable?: boolean } & Record, 'db' | 'auth' | 'extra'>, Omit<{ extra: boolean }, never> & Record, { input: string }, { output: number }, @@ -147,7 +147,7 @@ describe('DecoratedMiddleware', () => { expectTypeOf(decorated.concat(mid, () => { })).toEqualTypeOf< DecoratedMiddleware< - CurrentContext & Omit<{ cacheable?: boolean }, 'db' | 'auth' | 'extra'>, + CurrentContext & Omit<{ cacheable?: boolean } & Record, 'db' | 'auth' | 'extra'>, Omit<{ extra: boolean }, never> & Record, { input: string }, { output: number }, diff --git a/packages/server/src/procedure-decorated.test-d.ts b/packages/server/src/procedure-decorated.test-d.ts index 0e6cd15d3..d2de10b61 100644 --- a/packages/server/src/procedure-decorated.test-d.ts +++ b/packages/server/src/procedure-decorated.test-d.ts @@ -168,7 +168,7 @@ describe('DecoratedProcedure', () => { }) it('with TInContext', () => { - const mid = {} as Middleware<{ cacheable?: boolean }, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> + const mid = {} as Middleware<{ cacheable?: boolean } & Record, Record, unknown, any, ORPCErrorConstructorMap, BaseMeta> expectTypeOf(builder.use(mid)).toEqualTypeOf< DecoratedProcedure< From f1fb34aa2cc6c8763683f4c49c9ed3e438c07d27 Mon Sep 17 00:00:00 2001 From: unnoq Date: Sat, 15 Mar 2025 08:55:33 +0700 Subject: [PATCH 2/4] fix(server): `has no properties in common with type` problem --- .../server/src/builder-variants.test-d.ts | 50 +++++++++---------- packages/server/src/builder.test-d.ts | 17 +++---- packages/server/src/builder.ts | 6 ++- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/packages/server/src/builder-variants.test-d.ts b/packages/server/src/builder-variants.test-d.ts index 8108f8e72..45bd355d3 100644 --- a/packages/server/src/builder-variants.test-d.ts +++ b/packages/server/src/builder-variants.test-d.ts @@ -236,18 +236,17 @@ describe('BuilderWithMiddlewares', () => { builder.router({ // @ts-expect-error - initial context is not match - ping: {} as Procedure<{ invalid: true }, Context, undefined, undefined, unknown, Record, BaseMeta>, + ping: {} as Procedure<{ invalid: true }, any, any, any, any, any>, }) builder.router({ // @ts-expect-error - meta def is not match ping: {} as Procedure< - Context, - Context, - undefined, - undefined, - unknown, - Record, + any, + any, + any, + any, + any, { invalid: true } >, }) @@ -261,7 +260,7 @@ describe('BuilderWithMiddlewares', () => { // @ts-expect-error - initial context is not match builder.lazy(() => Promise.resolve({ default: { - ping: {} as Procedure<{ invalid: true }, Context, AnySchema, AnySchema, Record, BaseMeta>, + ping: {} as Procedure<{ invalid: true }, any, any, any, any, any>, }, })) @@ -269,11 +268,11 @@ describe('BuilderWithMiddlewares', () => { builder.lazy(() => Promise.resolve({ default: { ping: {} as Procedure< - Context, - Context, - AnySchema, - AnySchema, - Record, + any, + any, + any, + any, + any, { invalid: true } >, }, @@ -1208,18 +1207,17 @@ describe('RouterBuilder', () => { builder.router({ // @ts-expect-error - initial context is not match - ping: {} as Procedure<{ invalid: true }, Context, undefined, undefined, unknown, Record, BaseMeta>, + ping: {} as Procedure<{ invalid: true }, any, any, any, any, any>, }) builder.router({ // @ts-expect-error - meta def is not match ping: {} as Procedure< - Context, - Context, - undefined, - undefined, - unknown, - Record, + any, + any, + any, + any, + any, { invalid: true } >, }) @@ -1233,7 +1231,7 @@ describe('RouterBuilder', () => { // @ts-expect-error - initial context is not match builder.lazy(() => Promise.resolve({ default: { - ping: {} as Procedure<{ invalid: true }, Context, AnySchema, AnySchema, Record, BaseMeta>, + ping: {} as Procedure<{ invalid: true }, any, any, any, any, any>, }, })) @@ -1241,11 +1239,11 @@ describe('RouterBuilder', () => { builder.lazy(() => Promise.resolve({ default: { ping: {} as Procedure< - Context, - Context, - AnySchema, - AnySchema, - Record, + any, + any, + any, + any, + any, { invalid: true } >, }, diff --git a/packages/server/src/builder.test-d.ts b/packages/server/src/builder.test-d.ts index bc256be52..f21660790 100644 --- a/packages/server/src/builder.test-d.ts +++ b/packages/server/src/builder.test-d.ts @@ -62,7 +62,7 @@ describe('Builder', () => { it('.$context', () => { expectTypeOf(builder.$context()).toEqualTypeOf< Builder< - Context, + Context & Record, Context, typeof inputSchema, typeof outputSchema, @@ -72,7 +72,7 @@ describe('Builder', () => { >() expectTypeOf(builder.$context<{ anything: string }>()).toEqualTypeOf< Builder< - { anything: string }, + { anything: string } & Record, { anything: string }, typeof inputSchema, typeof outputSchema, @@ -437,18 +437,17 @@ describe('Builder', () => { builder.router({ // @ts-expect-error - initial context is not match - ping: {} as Procedure<{ invalid: true }, Context, undefined, undefined, unknown, Record, BaseMeta>, + ping: {} as Procedure<{ invalid: true }, any, any, any, any, any>, }) builder.router({ // @ts-expect-error - meta def is not match ping: {} as Procedure< - Context, - Context, - undefined, - undefined, - unknown, - Record, + any, + any, + any, + any, + any, { invalid: true } >, }) diff --git a/packages/server/src/builder.ts b/packages/server/src/builder.ts index f1a4afe74..025731d85 100644 --- a/packages/server/src/builder.ts +++ b/packages/server/src/builder.ts @@ -67,7 +67,11 @@ export class Builder< /** * Reset initial context */ - $context(): Builder { + $context(): Builder, U, TInputSchema, TOutputSchema, TErrorMap, TMeta> { + /** + * We need `& Record` to deal with `has no properties in common with type` error + */ + return new Builder({ ...this['~orpc'], middlewares: [], From 76cf4ae60eca77ab10e9ee2684061c8b0a2a7d3d Mon Sep 17 00:00:00 2001 From: unnoq Date: Sat, 15 Mar 2025 08:59:56 +0700 Subject: [PATCH 3/4] $meta --- packages/server/src/builder.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/server/src/builder.ts b/packages/server/src/builder.ts index 025731d85..3b3900ea5 100644 --- a/packages/server/src/builder.ts +++ b/packages/server/src/builder.ts @@ -85,7 +85,11 @@ export class Builder< */ $meta( initialMeta: U, - ): Builder { + ): Builder> { + /** + * We need `& Record` to deal with `has no properties in common with type` error + */ + return new Builder({ ...this['~orpc'], meta: initialMeta, From 1c19511282d54d62245a53d1a05299f82fc19edf Mon Sep 17 00:00:00 2001 From: unnoq Date: Sat, 15 Mar 2025 09:03:57 +0700 Subject: [PATCH 4/4] fix tests --- packages/server/src/builder.test-d.ts | 2 +- packages/server/src/context.test-d.ts | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/server/src/builder.test-d.ts b/packages/server/src/builder.test-d.ts index f21660790..1bcbfdc52 100644 --- a/packages/server/src/builder.test-d.ts +++ b/packages/server/src/builder.test-d.ts @@ -90,7 +90,7 @@ describe('Builder', () => { typeof inputSchema, typeof outputSchema, typeof baseErrorMap, - { auth?: boolean } + { auth?: boolean } & Record > >() diff --git a/packages/server/src/context.test-d.ts b/packages/server/src/context.test-d.ts index 24284d3ff..d323bf837 100644 --- a/packages/server/src/context.test-d.ts +++ b/packages/server/src/context.test-d.ts @@ -20,12 +20,20 @@ it('ContextExtendsGuard', () => { expectTypeOf>().toEqualTypeOf() expectTypeOf < ContextExtendsGuard< { a: string, b: string }, Empty>>().toEqualTypeOf() expectTypeOf < ContextExtendsGuard< { a: string, b: string }, Record>>().toEqualTypeOf() - expectTypeOf < ContextExtendsGuard< { a: string, b: string }, { g?: string }>>().toEqualTypeOf() expectTypeOf>().toEqualTypeOf() - expectTypeOf>().toEqualTypeOf() - expectTypeOf>().toEqualTypeOf() expectTypeOf < ContextExtendsGuard < { a: string }, { a: string, b: string }>>().toEqualTypeOf() expectTypeOf < ContextExtendsGuard < { a: number }, { a: string }>>().toEqualTypeOf() expectTypeOf>().toEqualTypeOf() + + expectTypeOf>().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() + expectTypeOf>().toEqualTypeOf() + + /** + * We can use `& Record` to deal with `has no properties in common with type` error + */ + expectTypeOf>>().toEqualTypeOf() + expectTypeOf>>().toEqualTypeOf() + expectTypeOf>>().toEqualTypeOf() })