Skip to content

Commit ba53a01

Browse files
authored
fix(server): has no properties in common with type ts-problem (#244)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Refactor** - Improved internal type structures for middleware, procedures, and context to bolster compatibility and flexibility. - **Tests** - Updated type assertions across test cases to ensure consistency and reliability, including modifications to expected outcomes in `ContextExtendsGuard` tests. These behind-the-scenes improvements streamline integration points and enhance overall robustness, providing a smoother experience for developers using the system. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 9fc14d1 commit ba53a01

10 files changed

+70
-57
lines changed

packages/server/src/builder-variants.test-d.ts

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ describe('BuilderWithMiddlewares', () => {
108108
})
109109

110110
it('with TInContext', () => {
111-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
111+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
112112

113113
expectTypeOf(builder.use(mid)).toEqualTypeOf<
114114
BuilderWithMiddlewares<
@@ -236,18 +236,17 @@ describe('BuilderWithMiddlewares', () => {
236236

237237
builder.router({
238238
// @ts-expect-error - initial context is not match
239-
ping: {} as Procedure<{ invalid: true }, Context, undefined, undefined, unknown, Record<never, never>, BaseMeta>,
239+
ping: {} as Procedure<{ invalid: true }, any, any, any, any, any>,
240240
})
241241

242242
builder.router({
243243
// @ts-expect-error - meta def is not match
244244
ping: {} as Procedure<
245-
Context,
246-
Context,
247-
undefined,
248-
undefined,
249-
unknown,
250-
Record<never, never>,
245+
any,
246+
any,
247+
any,
248+
any,
249+
any,
251250
{ invalid: true }
252251
>,
253252
})
@@ -261,19 +260,19 @@ describe('BuilderWithMiddlewares', () => {
261260
// @ts-expect-error - initial context is not match
262261
builder.lazy(() => Promise.resolve({
263262
default: {
264-
ping: {} as Procedure<{ invalid: true }, Context, AnySchema, AnySchema, Record<never, never>, BaseMeta>,
263+
ping: {} as Procedure<{ invalid: true }, any, any, any, any, any>,
265264
},
266265
}))
267266

268267
// @ts-expect-error - meta def is not match
269268
builder.lazy(() => Promise.resolve({
270269
default: {
271270
ping: {} as Procedure<
272-
Context,
273-
Context,
274-
AnySchema,
275-
AnySchema,
276-
Record<never, never>,
271+
any,
272+
any,
273+
any,
274+
any,
275+
any,
277276
{ invalid: true }
278277
>,
279278
},
@@ -368,7 +367,7 @@ describe('ProcedureBuilder', () => {
368367
})
369368

370369
it('with TInContext', () => {
371-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
370+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
372371

373372
expectTypeOf(builder.use(mid)).toEqualTypeOf<
374373
ProcedureBuilder<
@@ -610,7 +609,7 @@ describe('ProcedureBuilderWithInput', () => {
610609
})
611610

612611
it('with TInContext', () => {
613-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
612+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
614613

615614
expectTypeOf(builder.use(mid)).toEqualTypeOf<
616615
ProcedureBuilderWithInput<
@@ -799,7 +798,7 @@ describe('ProcedureBuilderWithOutput', () => {
799798
})
800799

801800
it('with TInContext', () => {
802-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
801+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
803802

804803
expectTypeOf(builder.use(mid)).toEqualTypeOf<
805804
ProcedureBuilderWithOutput<
@@ -1028,7 +1027,7 @@ describe('ProcedureBuilderWithInputOutput', () => {
10281027
})
10291028

10301029
it('with TInContext', () => {
1031-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
1030+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
10321031

10331032
expectTypeOf(builder.use(mid)).toEqualTypeOf<
10341033
ProcedureBuilderWithInputOutput<
@@ -1173,7 +1172,7 @@ describe('RouterBuilder', () => {
11731172
})
11741173

11751174
it('with TInContext', () => {
1176-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
1175+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
11771176

11781177
expectTypeOf(builder.use(mid)).toEqualTypeOf<
11791178
RouterBuilder<
@@ -1208,18 +1207,17 @@ describe('RouterBuilder', () => {
12081207

12091208
builder.router({
12101209
// @ts-expect-error - initial context is not match
1211-
ping: {} as Procedure<{ invalid: true }, Context, undefined, undefined, unknown, Record<never, never>, BaseMeta>,
1210+
ping: {} as Procedure<{ invalid: true }, any, any, any, any, any>,
12121211
})
12131212

12141213
builder.router({
12151214
// @ts-expect-error - meta def is not match
12161215
ping: {} as Procedure<
1217-
Context,
1218-
Context,
1219-
undefined,
1220-
undefined,
1221-
unknown,
1222-
Record<never, never>,
1216+
any,
1217+
any,
1218+
any,
1219+
any,
1220+
any,
12231221
{ invalid: true }
12241222
>,
12251223
})
@@ -1233,19 +1231,19 @@ describe('RouterBuilder', () => {
12331231
// @ts-expect-error - initial context is not match
12341232
builder.lazy(() => Promise.resolve({
12351233
default: {
1236-
ping: {} as Procedure<{ invalid: true }, Context, AnySchema, AnySchema, Record<never, never>, BaseMeta>,
1234+
ping: {} as Procedure<{ invalid: true }, any, any, any, any, any>,
12371235
},
12381236
}))
12391237

12401238
// @ts-expect-error - meta def is not match
12411239
builder.lazy(() => Promise.resolve({
12421240
default: {
12431241
ping: {} as Procedure<
1244-
Context,
1245-
Context,
1246-
AnySchema,
1247-
AnySchema,
1248-
Record<never, never>,
1242+
any,
1243+
any,
1244+
any,
1245+
any,
1246+
any,
12491247
{ invalid: true }
12501248
>,
12511249
},

packages/server/src/builder.test-d.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ describe('Builder', () => {
6262
it('.$context', () => {
6363
expectTypeOf(builder.$context()).toEqualTypeOf<
6464
Builder<
65-
Context,
65+
Context & Record<never, never>,
6666
Context,
6767
typeof inputSchema,
6868
typeof outputSchema,
@@ -72,7 +72,7 @@ describe('Builder', () => {
7272
>()
7373
expectTypeOf(builder.$context<{ anything: string }>()).toEqualTypeOf<
7474
Builder<
75-
{ anything: string },
75+
{ anything: string } & Record<never, never>,
7676
{ anything: string },
7777
typeof inputSchema,
7878
typeof outputSchema,
@@ -90,7 +90,7 @@ describe('Builder', () => {
9090
typeof inputSchema,
9191
typeof outputSchema,
9292
typeof baseErrorMap,
93-
{ auth?: boolean }
93+
{ auth?: boolean } & Record<never, never>
9494
>
9595
>()
9696

@@ -298,7 +298,7 @@ describe('Builder', () => {
298298
})
299299

300300
it('with TInContext', () => {
301-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
301+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
302302

303303
expectTypeOf(builder.use(mid)).toEqualTypeOf<
304304
BuilderWithMiddlewares<
@@ -437,18 +437,17 @@ describe('Builder', () => {
437437

438438
builder.router({
439439
// @ts-expect-error - initial context is not match
440-
ping: {} as Procedure<{ invalid: true }, Context, undefined, undefined, unknown, Record<never, never>, BaseMeta>,
440+
ping: {} as Procedure<{ invalid: true }, any, any, any, any, any>,
441441
})
442442

443443
builder.router({
444444
// @ts-expect-error - meta def is not match
445445
ping: {} as Procedure<
446-
Context,
447-
Context,
448-
undefined,
449-
undefined,
450-
unknown,
451-
Record<never, never>,
446+
any,
447+
any,
448+
any,
449+
any,
450+
any,
452451
{ invalid: true }
453452
>,
454453
})

packages/server/src/builder.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,11 @@ export class Builder<
6767
/**
6868
* Reset initial context
6969
*/
70-
$context<U extends Context>(): Builder<U, U, TInputSchema, TOutputSchema, TErrorMap, TMeta> {
70+
$context<U extends Context>(): Builder<U & Record<never, never>, U, TInputSchema, TOutputSchema, TErrorMap, TMeta> {
71+
/**
72+
* We need `& Record<never, never>` to deal with `has no properties in common with type` error
73+
*/
74+
7175
return new Builder({
7276
...this['~orpc'],
7377
middlewares: [],
@@ -81,7 +85,11 @@ export class Builder<
8185
*/
8286
$meta<U extends Meta>(
8387
initialMeta: U,
84-
): Builder<TInitialContext, TCurrentContext, TInputSchema, TOutputSchema, TErrorMap, U> {
88+
): Builder<TInitialContext, TCurrentContext, TInputSchema, TOutputSchema, TErrorMap, U & Record<never, never>> {
89+
/**
90+
* We need `& Record<never, never>` to deal with `has no properties in common with type` error
91+
*/
92+
8593
return new Builder({
8694
...this['~orpc'],
8795
meta: initialMeta,

packages/server/src/context.test-d.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,20 @@ it('ContextExtendsGuard', () => {
2020
expectTypeOf<ContextExtendsGuard<{ a: string }, { a: string }>>().toEqualTypeOf<unknown>()
2121
expectTypeOf < ContextExtendsGuard< { a: string, b: string }, Empty>>().toEqualTypeOf<unknown>()
2222
expectTypeOf < ContextExtendsGuard< { a: string, b: string }, Record<never, never>>>().toEqualTypeOf<unknown>()
23-
expectTypeOf < ContextExtendsGuard< { a: string, b: string }, { g?: string }>>().toEqualTypeOf<unknown>()
2423
expectTypeOf<ContextExtendsGuard<Empty, { a?: string }>>().toEqualTypeOf<unknown>()
25-
expectTypeOf<ContextExtendsGuard<{ b: string }, { a?: string }>>().toEqualTypeOf<unknown>()
26-
expectTypeOf<ContextExtendsGuard<{ b?: string }, { a?: string }>>().toEqualTypeOf<unknown>()
2724

2825
expectTypeOf < ContextExtendsGuard < { a: string }, { a: string, b: string }>>().toEqualTypeOf<never>()
2926
expectTypeOf < ContextExtendsGuard < { a: number }, { a: string }>>().toEqualTypeOf<never>()
3027
expectTypeOf<ContextExtendsGuard<Empty, { a: string }>>().toEqualTypeOf<never>()
28+
29+
expectTypeOf<ContextExtendsGuard<{ a: string, b: string }, { g?: string }>>().toEqualTypeOf<never>()
30+
expectTypeOf<ContextExtendsGuard<{ b: string }, { a?: string }>>().toEqualTypeOf<never>()
31+
expectTypeOf<ContextExtendsGuard<{ b?: string }, { a?: string }>>().toEqualTypeOf<never>()
32+
33+
/**
34+
* We can use `& Record<never, never>` to deal with `has no properties in common with type` error
35+
*/
36+
expectTypeOf<ContextExtendsGuard<{ a: string, b: string }, { g?: string } & Record<never, never>>>().toEqualTypeOf<unknown>()
37+
expectTypeOf<ContextExtendsGuard<{ b: string }, { a?: string } & Record<never, never>>>().toEqualTypeOf<unknown>()
38+
expectTypeOf<ContextExtendsGuard<{ b?: string }, { a?: string } & Record<never, never>>>().toEqualTypeOf<unknown>()
3139
})

packages/server/src/context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ export function mergeCurrentContext<T extends Context, U extends Context>(
1515
return { ...context, ...other }
1616
}
1717

18-
export type ContextExtendsGuard<T extends Context, U extends Context> = T extends T & U ? unknown : never
18+
export type ContextExtendsGuard<T extends Context, U extends Context> = T extends U ? unknown : never

packages/server/src/implementer-procedure.test-d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ describe('ImplementedProcedure', () => {
140140
})
141141

142142
it('with TInContext', () => {
143-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
143+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
144144

145145
expectTypeOf(implemented.use(mid)).toEqualTypeOf<
146146
ImplementedProcedure<
@@ -322,7 +322,7 @@ describe('ProcedureImplementer', () => {
322322
})
323323

324324
it('with TInContext', () => {
325-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
325+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
326326

327327
expectTypeOf(builder.use(mid)).toEqualTypeOf<
328328
ProcedureImplementer<

packages/server/src/implementer-variants.test-d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ describe('ImplementerWithMiddlewares', () => {
5656
})
5757

5858
it('with TInContext', () => {
59-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
59+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
6060

6161
expectTypeOf(implementer.use(mid)).toEqualTypeOf<
6262
ImplementerInternalWithMiddlewares<

packages/server/src/implementer.test-d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ describe('Implementer', () => {
125125
})
126126

127127
it('with TInContext', () => {
128-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
128+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, unknown, ORPCErrorConstructorMap<any>, BaseMeta>
129129

130130
expectTypeOf(implementer.use(mid)).toEqualTypeOf<
131131
ImplementerInternalWithMiddlewares<

packages/server/src/middleware-decorated.test-d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,11 @@ describe('DecoratedMiddleware', () => {
132132
})
133133

134134
it('with TInContext', () => {
135-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
135+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
136136

137137
expectTypeOf(decorated.concat(mid)).toEqualTypeOf<
138138
DecoratedMiddleware<
139-
CurrentContext & Omit<{ cacheable?: boolean }, 'db' | 'auth' | 'extra'>,
139+
CurrentContext & Omit<{ cacheable?: boolean } & Record<never, never>, 'db' | 'auth' | 'extra'>,
140140
Omit<{ extra: boolean }, never> & Record<never, never>,
141141
{ input: string },
142142
{ output: number },
@@ -147,7 +147,7 @@ describe('DecoratedMiddleware', () => {
147147

148148
expectTypeOf(decorated.concat(mid, () => { })).toEqualTypeOf<
149149
DecoratedMiddleware<
150-
CurrentContext & Omit<{ cacheable?: boolean }, 'db' | 'auth' | 'extra'>,
150+
CurrentContext & Omit<{ cacheable?: boolean } & Record<never, never>, 'db' | 'auth' | 'extra'>,
151151
Omit<{ extra: boolean }, never> & Record<never, never>,
152152
{ input: string },
153153
{ output: number },

packages/server/src/procedure-decorated.test-d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ describe('DecoratedProcedure', () => {
168168
})
169169

170170
it('with TInContext', () => {
171-
const mid = {} as Middleware<{ cacheable?: boolean }, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
171+
const mid = {} as Middleware<{ cacheable?: boolean } & Record<never, never>, Record<never, never>, unknown, any, ORPCErrorConstructorMap<any>, BaseMeta>
172172

173173
expectTypeOf(builder.use(mid)).toEqualTypeOf<
174174
DecoratedProcedure<

0 commit comments

Comments
 (0)