Skip to content

Commit d7c6bfb

Browse files
authored
CODEGEN-840 - Handle empty object type better (#10409)
* Update ts-resolvers to handle {} correctly * Refactor types * Update ts-documents to handle {} better * Add changeset * Update tests
1 parent 1bb7aa3 commit d7c6bfb

23 files changed

+364
-238
lines changed

.changeset/long-dolphins-teach.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@graphql-codegen/visitor-plugin-common': major
3+
'@graphql-codegen/typescript-operations': major
4+
'@graphql-codegen/typescript-resolvers': major
5+
'@graphql-codegen/client-preset': major
6+
---
7+
8+
BREAKING CHANGE: Use Record<PropertyKey, never> instead of {} for empty object type

dev-test/modules/types.ts

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,12 @@ export type ResolverTypeWrapper<T> = Promise<T> | T;
9999
export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
100100
resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
101101
};
102-
export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
103-
| ResolverFn<TResult, TParent, TContext, TArgs>
104-
| ResolverWithResolve<TResult, TParent, TContext, TArgs>;
102+
export type Resolver<
103+
TResult,
104+
TParent = Record<PropertyKey, never>,
105+
TContext = Record<PropertyKey, never>,
106+
TArgs = Record<PropertyKey, never>
107+
> = ResolverFn<TResult, TParent, TContext, TArgs> | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
105108

106109
export type ResolverFn<TResult, TParent, TContext, TArgs> = (
107110
parent: TParent,
@@ -138,25 +141,36 @@ export type SubscriptionObject<TResult, TKey extends string, TParent, TContext,
138141
| SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>
139142
| SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;
140143

141-
export type SubscriptionResolver<TResult, TKey extends string, TParent = {}, TContext = {}, TArgs = {}> =
144+
export type SubscriptionResolver<
145+
TResult,
146+
TKey extends string,
147+
TParent = Record<PropertyKey, never>,
148+
TContext = Record<PropertyKey, never>,
149+
TArgs = Record<PropertyKey, never>
150+
> =
142151
| ((...args: any[]) => SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>)
143152
| SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>;
144153

145-
export type TypeResolveFn<TTypes, TParent = {}, TContext = {}> = (
154+
export type TypeResolveFn<TTypes, TParent = Record<PropertyKey, never>, TContext = Record<PropertyKey, never>> = (
146155
parent: TParent,
147156
context: TContext,
148157
info: GraphQLResolveInfo
149158
) => Maybe<TTypes> | Promise<Maybe<TTypes>>;
150159

151-
export type IsTypeOfResolverFn<T = {}, TContext = {}> = (
160+
export type IsTypeOfResolverFn<T = Record<PropertyKey, never>, TContext = Record<PropertyKey, never>> = (
152161
obj: T,
153162
context: TContext,
154163
info: GraphQLResolveInfo
155164
) => boolean | Promise<boolean>;
156165

157166
export type NextResolverFn<T> = () => Promise<T>;
158167

159-
export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs = {}> = (
168+
export type DirectiveResolverFn<
169+
TResult = Record<PropertyKey, never>,
170+
TParent = Record<PropertyKey, never>,
171+
TContext = Record<PropertyKey, never>,
172+
TArgs = Record<PropertyKey, never>
173+
> = (
160174
next: NextResolverFn<TResult>,
161175
parent: TParent,
162176
args: TArgs,
@@ -181,10 +195,10 @@ export type ResolversTypes = {
181195
Float: ResolverTypeWrapper<Scalars['Float']['output']>;
182196
ID: ResolverTypeWrapper<Scalars['ID']['output']>;
183197
Int: ResolverTypeWrapper<Scalars['Int']['output']>;
184-
Mutation: ResolverTypeWrapper<{}>;
198+
Mutation: ResolverTypeWrapper<Record<PropertyKey, never>>;
185199
PaymentOption: ResolverTypeWrapper<ResolversUnionTypes<ResolversTypes>['PaymentOption']>;
186200
Paypal: ResolverTypeWrapper<Paypal>;
187-
Query: ResolverTypeWrapper<{}>;
201+
Query: ResolverTypeWrapper<Record<PropertyKey, never>>;
188202
String: ResolverTypeWrapper<Scalars['String']['output']>;
189203
User: ResolverTypeWrapper<
190204
Omit<User, 'paymentOptions'> & { paymentOptions?: Maybe<Array<ResolversTypes['PaymentOption']>> }
@@ -204,10 +218,10 @@ export type ResolversParentTypes = {
204218
Float: Scalars['Float']['output'];
205219
ID: Scalars['ID']['output'];
206220
Int: Scalars['Int']['output'];
207-
Mutation: {};
221+
Mutation: Record<PropertyKey, never>;
208222
PaymentOption: ResolversUnionTypes<ResolversParentTypes>['PaymentOption'];
209223
Paypal: Paypal;
210-
Query: {};
224+
Query: Record<PropertyKey, never>;
211225
String: Scalars['String']['output'];
212226
User: Omit<User, 'paymentOptions'> & { paymentOptions?: Maybe<Array<ResolversParentTypes['PaymentOption']>> };
213227
};

dev-test/subpath-import/result.d.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,12 @@ export type ResolverTypeWrapper<T> = Promise<T> | T;
4848
export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
4949
resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
5050
};
51-
export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
52-
| ResolverFn<TResult, TParent, TContext, TArgs>
53-
| ResolverWithResolve<TResult, TParent, TContext, TArgs>;
51+
export type Resolver<
52+
TResult,
53+
TParent = Record<PropertyKey, never>,
54+
TContext = Record<PropertyKey, never>,
55+
TArgs = Record<PropertyKey, never>
56+
> = ResolverFn<TResult, TParent, TContext, TArgs> | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
5457

5558
export type ResolverFn<TResult, TParent, TContext, TArgs> = (
5659
parent: TParent,
@@ -87,25 +90,36 @@ export type SubscriptionObject<TResult, TKey extends string, TParent, TContext,
8790
| SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>
8891
| SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;
8992

90-
export type SubscriptionResolver<TResult, TKey extends string, TParent = {}, TContext = {}, TArgs = {}> =
93+
export type SubscriptionResolver<
94+
TResult,
95+
TKey extends string,
96+
TParent = Record<PropertyKey, never>,
97+
TContext = Record<PropertyKey, never>,
98+
TArgs = Record<PropertyKey, never>
99+
> =
91100
| ((...args: any[]) => SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>)
92101
| SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>;
93102

94-
export type TypeResolveFn<TTypes, TParent = {}, TContext = {}> = (
103+
export type TypeResolveFn<TTypes, TParent = Record<PropertyKey, never>, TContext = Record<PropertyKey, never>> = (
95104
parent: TParent,
96105
context: TContext,
97106
info: GraphQLResolveInfo
98107
) => Maybe<TTypes> | Promise<Maybe<TTypes>>;
99108

100-
export type IsTypeOfResolverFn<T = {}, TContext = {}> = (
109+
export type IsTypeOfResolverFn<T = Record<PropertyKey, never>, TContext = Record<PropertyKey, never>> = (
101110
obj: T,
102111
context: TContext,
103112
info: GraphQLResolveInfo
104113
) => boolean | Promise<boolean>;
105114

106115
export type NextResolverFn<T> = () => Promise<T>;
107116

108-
export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs = {}> = (
117+
export type DirectiveResolverFn<
118+
TResult = Record<PropertyKey, never>,
119+
TParent = Record<PropertyKey, never>,
120+
TContext = Record<PropertyKey, never>,
121+
TArgs = Record<PropertyKey, never>
122+
> = (
109123
next: NextResolverFn<TResult>,
110124
parent: TParent,
111125
args: TArgs,

dev-test/test-schema/resolvers-federation.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,12 @@ export type GraphQLRecursivePick<T, S> = { [K in keyof T & keyof S]: ScalarCheck
6363
export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
6464
resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
6565
};
66-
export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
67-
| ResolverFn<TResult, TParent, TContext, TArgs>
68-
| ResolverWithResolve<TResult, TParent, TContext, TArgs>;
66+
export type Resolver<
67+
TResult,
68+
TParent = Record<PropertyKey, never>,
69+
TContext = Record<PropertyKey, never>,
70+
TArgs = Record<PropertyKey, never>
71+
> = ResolverFn<TResult, TParent, TContext, TArgs> | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
6972

7073
export type ResolverFn<TResult, TParent, TContext, TArgs> = (
7174
parent: TParent,
@@ -102,25 +105,36 @@ export type SubscriptionObject<TResult, TKey extends string, TParent, TContext,
102105
| SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>
103106
| SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;
104107

105-
export type SubscriptionResolver<TResult, TKey extends string, TParent = {}, TContext = {}, TArgs = {}> =
108+
export type SubscriptionResolver<
109+
TResult,
110+
TKey extends string,
111+
TParent = Record<PropertyKey, never>,
112+
TContext = Record<PropertyKey, never>,
113+
TArgs = Record<PropertyKey, never>
114+
> =
106115
| ((...args: any[]) => SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>)
107116
| SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>;
108117

109-
export type TypeResolveFn<TTypes, TParent = {}, TContext = {}> = (
118+
export type TypeResolveFn<TTypes, TParent = Record<PropertyKey, never>, TContext = Record<PropertyKey, never>> = (
110119
parent: TParent,
111120
context: TContext,
112121
info: GraphQLResolveInfo
113122
) => Maybe<TTypes> | Promise<Maybe<TTypes>>;
114123

115-
export type IsTypeOfResolverFn<T = {}, TContext = {}> = (
124+
export type IsTypeOfResolverFn<T = Record<PropertyKey, never>, TContext = Record<PropertyKey, never>> = (
116125
obj: T,
117126
context: TContext,
118127
info: GraphQLResolveInfo
119128
) => boolean | Promise<boolean>;
120129

121130
export type NextResolverFn<T> = () => Promise<T>;
122131

123-
export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs = {}> = (
132+
export type DirectiveResolverFn<
133+
TResult = Record<PropertyKey, never>,
134+
TParent = Record<PropertyKey, never>,
135+
TContext = Record<PropertyKey, never>,
136+
TArgs = Record<PropertyKey, never>
137+
> = (
124138
next: NextResolverFn<TResult>,
125139
parent: TParent,
126140
args: TArgs,
@@ -139,7 +153,10 @@ export type FederationReferenceTypes = {
139153
| GraphQLRecursivePick<FederationTypes['User'], { id: true }>
140154
| GraphQLRecursivePick<FederationTypes['User'], { name: true }>
141155
) &
142-
({} | GraphQLRecursivePick<FederationTypes['User'], { address: { city: true; lines: { line2: true } } }>);
156+
(
157+
| Record<PropertyKey, never>
158+
| GraphQLRecursivePick<FederationTypes['User'], { address: { city: true; lines: { line2: true } } }>
159+
);
143160
};
144161

145162
/** Mapping between all available schema types and the resolvers types */
@@ -149,7 +166,7 @@ export type ResolversTypes = {
149166
Book: ResolverTypeWrapper<Book>;
150167
ID: ResolverTypeWrapper<Scalars['ID']['output']>;
151168
Lines: ResolverTypeWrapper<Lines>;
152-
Query: ResolverTypeWrapper<{}>;
169+
Query: ResolverTypeWrapper<Record<PropertyKey, never>>;
153170
User: ResolverTypeWrapper<User>;
154171
Int: ResolverTypeWrapper<Scalars['Int']['output']>;
155172
Boolean: ResolverTypeWrapper<Scalars['Boolean']['output']>;
@@ -162,7 +179,7 @@ export type ResolversParentTypes = {
162179
Book: Book;
163180
ID: Scalars['ID']['output'];
164181
Lines: Lines;
165-
Query: {};
182+
Query: Record<PropertyKey, never>;
166183
User: User | FederationReferenceTypes['User'];
167184
Int: Scalars['Int']['output'];
168185
Boolean: Scalars['Boolean']['output'];

dev-test/test-schema/resolvers-root.ts

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,12 @@ export type ResolverTypeWrapper<T> = Promise<T> | T;
4949
export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
5050
resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
5151
};
52-
export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
53-
| ResolverFn<TResult, TParent, TContext, TArgs>
54-
| ResolverWithResolve<TResult, TParent, TContext, TArgs>;
52+
export type Resolver<
53+
TResult,
54+
TParent = Record<PropertyKey, never>,
55+
TContext = Record<PropertyKey, never>,
56+
TArgs = Record<PropertyKey, never>
57+
> = ResolverFn<TResult, TParent, TContext, TArgs> | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
5558

5659
export type ResolverFn<TResult, TParent, TContext, TArgs> = (
5760
parent: TParent,
@@ -88,25 +91,36 @@ export type SubscriptionObject<TResult, TKey extends string, TParent, TContext,
8891
| SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>
8992
| SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;
9093

91-
export type SubscriptionResolver<TResult, TKey extends string, TParent = {}, TContext = {}, TArgs = {}> =
94+
export type SubscriptionResolver<
95+
TResult,
96+
TKey extends string,
97+
TParent = Record<PropertyKey, never>,
98+
TContext = Record<PropertyKey, never>,
99+
TArgs = Record<PropertyKey, never>
100+
> =
92101
| ((...args: any[]) => SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>)
93102
| SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>;
94103

95-
export type TypeResolveFn<TTypes, TParent = {}, TContext = {}> = (
104+
export type TypeResolveFn<TTypes, TParent = Record<PropertyKey, never>, TContext = Record<PropertyKey, never>> = (
96105
parent: TParent,
97106
context: TContext,
98107
info: GraphQLResolveInfo
99108
) => Maybe<TTypes> | Promise<Maybe<TTypes>>;
100109

101-
export type IsTypeOfResolverFn<T = {}, TContext = {}> = (
110+
export type IsTypeOfResolverFn<T = Record<PropertyKey, never>, TContext = Record<PropertyKey, never>> = (
102111
obj: T,
103112
context: TContext,
104113
info: GraphQLResolveInfo
105114
) => boolean | Promise<boolean>;
106115

107116
export type NextResolverFn<T> = () => Promise<T>;
108117

109-
export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs = {}> = (
118+
export type DirectiveResolverFn<
119+
TResult = Record<PropertyKey, never>,
120+
TParent = Record<PropertyKey, never>,
121+
TContext = Record<PropertyKey, never>,
122+
TArgs = Record<PropertyKey, never>
123+
> = (
110124
next: NextResolverFn<TResult>,
111125
parent: TParent,
112126
args: TArgs,
@@ -119,9 +133,9 @@ export type ResolversTypes = {
119133
Boolean: ResolverTypeWrapper<Scalars['Boolean']['output']>;
120134
Int: ResolverTypeWrapper<Scalars['Int']['output']>;
121135
Query: ResolverTypeWrapper<Query>;
122-
QueryRoot: ResolverTypeWrapper<{}>;
136+
QueryRoot: ResolverTypeWrapper<Record<PropertyKey, never>>;
123137
String: ResolverTypeWrapper<Scalars['String']['output']>;
124-
SubscriptionRoot: ResolverTypeWrapper<{}>;
138+
SubscriptionRoot: ResolverTypeWrapper<Record<PropertyKey, never>>;
125139
User: ResolverTypeWrapper<User>;
126140
};
127141

@@ -130,9 +144,9 @@ export type ResolversParentTypes = {
130144
Boolean: Scalars['Boolean']['output'];
131145
Int: Scalars['Int']['output'];
132146
Query: Query;
133-
QueryRoot: {};
147+
QueryRoot: Record<PropertyKey, never>;
134148
String: Scalars['String']['output'];
135-
SubscriptionRoot: {};
149+
SubscriptionRoot: Record<PropertyKey, never>;
136150
User: User;
137151
};
138152

dev-test/test-schema/resolvers-stitching.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ export type NewStitchingResolver<TResult, TParent, TContext, TArgs> = {
5959
export type StitchingResolver<TResult, TParent, TContext, TArgs> =
6060
| LegacyStitchingResolver<TResult, TParent, TContext, TArgs>
6161
| NewStitchingResolver<TResult, TParent, TContext, TArgs>;
62-
export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
62+
export type Resolver<
63+
TResult,
64+
TParent = Record<PropertyKey, never>,
65+
TContext = Record<PropertyKey, never>,
66+
TArgs = Record<PropertyKey, never>
67+
> =
6368
| ResolverFn<TResult, TParent, TContext, TArgs>
6469
| ResolverWithResolve<TResult, TParent, TContext, TArgs>
6570
| StitchingResolver<TResult, TParent, TContext, TArgs>;
@@ -99,25 +104,36 @@ export type SubscriptionObject<TResult, TKey extends string, TParent, TContext,
99104
| SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>
100105
| SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;
101106

102-
export type SubscriptionResolver<TResult, TKey extends string, TParent = {}, TContext = {}, TArgs = {}> =
107+
export type SubscriptionResolver<
108+
TResult,
109+
TKey extends string,
110+
TParent = Record<PropertyKey, never>,
111+
TContext = Record<PropertyKey, never>,
112+
TArgs = Record<PropertyKey, never>
113+
> =
103114
| ((...args: any[]) => SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>)
104115
| SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>;
105116

106-
export type TypeResolveFn<TTypes, TParent = {}, TContext = {}> = (
117+
export type TypeResolveFn<TTypes, TParent = Record<PropertyKey, never>, TContext = Record<PropertyKey, never>> = (
107118
parent: TParent,
108119
context: TContext,
109120
info: GraphQLResolveInfo
110121
) => Maybe<TTypes> | Promise<Maybe<TTypes>>;
111122

112-
export type IsTypeOfResolverFn<T = {}, TContext = {}> = (
123+
export type IsTypeOfResolverFn<T = Record<PropertyKey, never>, TContext = Record<PropertyKey, never>> = (
113124
obj: T,
114125
context: TContext,
115126
info: GraphQLResolveInfo
116127
) => boolean | Promise<boolean>;
117128

118129
export type NextResolverFn<T> = () => Promise<T>;
119130

120-
export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs = {}> = (
131+
export type DirectiveResolverFn<
132+
TResult = Record<PropertyKey, never>,
133+
TParent = Record<PropertyKey, never>,
134+
TContext = Record<PropertyKey, never>,
135+
TArgs = Record<PropertyKey, never>
136+
> = (
121137
next: NextResolverFn<TResult>,
122138
parent: TParent,
123139
args: TArgs,
@@ -129,7 +145,7 @@ export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs
129145
export type ResolversTypes = {
130146
Boolean: ResolverTypeWrapper<Scalars['Boolean']['output']>;
131147
Int: ResolverTypeWrapper<Scalars['Int']['output']>;
132-
Query: ResolverTypeWrapper<{}>;
148+
Query: ResolverTypeWrapper<Record<PropertyKey, never>>;
133149
String: ResolverTypeWrapper<Scalars['String']['output']>;
134150
User: ResolverTypeWrapper<User>;
135151
};
@@ -138,7 +154,7 @@ export type ResolversTypes = {
138154
export type ResolversParentTypes = {
139155
Boolean: Scalars['Boolean']['output'];
140156
Int: Scalars['Int']['output'];
141-
Query: {};
157+
Query: Record<PropertyKey, never>;
142158
String: Scalars['String']['output'];
143159
User: User;
144160
};

0 commit comments

Comments
 (0)