Skip to content

Commit db35312

Browse files
committed
refactor: export enums as module namespaces
TypeKind and DirectiveLocation now use the same representation as Kind: each enum member is a standalone ESM export with a matching type export, re-exported through a module namespace. This preserves the public TypeKind.SCALAR and DirectiveLocation.FIELD access pattern while avoiding a single object literal that makes all members part of the same runtime value. For example, TypeKind.SCALAR now resolves through the SCALAR named export from typeKind_.ts, which gives bundlers a smaller unit to analyze and tree-shake. BREAKING CHANGE: TypeKind and DirectiveLocation are now module namespace objects rather than plain object literals.
1 parent 2246333 commit db35312

12 files changed

Lines changed: 180 additions & 57 deletions

src/index.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,6 @@ export {
8686
GraphQLDeprecatedDirective,
8787
GraphQLSpecifiedByDirective,
8888
GraphQLOneOfDirective,
89-
// "Enum" of Type Kinds
90-
TypeKind,
9189
// Constant Deprecation Reason
9290
DEFAULT_DEPRECATION_REASON,
9391
// GraphQL Types for introspection.
@@ -229,12 +227,17 @@ export type {
229227
GraphQLDefaultInput,
230228
} from './type/index.ts';
231229

232-
// Parse and operate on GraphQL language source files.
233230
// @see https://github.com/typescript-eslint/typescript-eslint/issues/10313
234231
// Deno misclassifies this merged value+type re-export and requires `export type`.
235232
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
236233
// @ts-ignore TS1205
234+
export { TypeKind } from './type/typeKind.ts';
237235

236+
// Parse and operate on GraphQL language source files.
237+
// @see https://github.com/typescript-eslint/typescript-eslint/issues/10313
238+
// Deno misclassifies this merged value+type re-export and requires `export type`.
239+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
240+
// @ts-ignore TS1205
238241
export { Kind } from './language/kinds.ts';
239242

240243
export {
@@ -262,7 +265,6 @@ export {
262265
visitInParallel,
263266
getEnterLeaveForKind,
264267
BREAK,
265-
DirectiveLocation,
266268
// Predicates
267269
isDefinitionNode,
268270
isExecutableDefinitionNode,
@@ -278,6 +280,12 @@ export {
278280
isSubscriptionOperationDefinitionNode,
279281
} from './language/index.ts';
280282

283+
// @see https://github.com/typescript-eslint/typescript-eslint/issues/10313
284+
// Deno misclassifies this merged value+type re-export and requires `export type`.
285+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
286+
// @ts-ignore TS1205
287+
export { DirectiveLocation } from './language/directiveLocation.ts';
288+
281289
export type {
282290
ParseOptions,
283291
SourceLocation,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* eslint-disable no-unused-expressions */
2+
import { describe, it } from 'node:test';
3+
4+
import { DirectiveLocation } from '../index.ts';
5+
6+
describe('DirectiveLocation', () => {
7+
it('is a term level namespace with term level enum members', () => {
8+
const a: DirectiveLocation.QUERY = DirectiveLocation.QUERY;
9+
a;
10+
const b: DirectiveLocation = DirectiveLocation.QUERY;
11+
b;
12+
const c: DirectiveLocation = DirectiveLocation.FIELD_DEFINITION;
13+
c;
14+
});
15+
16+
it('is a type level namespace with type level enum members', () => {
17+
// @ts-expect-error
18+
const a: DirectiveLocation.QUERY = 'bad';
19+
a;
20+
const b: DirectiveLocation.QUERY = 'QUERY';
21+
b;
22+
// @ts-expect-error
23+
const c: DirectiveLocation = 'bad';
24+
c;
25+
const d: DirectiveLocation = 'QUERY';
26+
d;
27+
const e: DirectiveLocation = 'FIELD_DEFINITION';
28+
e;
29+
});
30+
});

src/language/directiveLocation.ts

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,10 @@
1+
/* eslint-disable import/no-namespace */
2+
import type * as DirectiveLocation_ from './directiveLocation_.ts';
3+
14
/**
25
* The set of allowed directive location values.
36
*/
4-
export const DirectiveLocation = {
5-
/** Request Definitions */
6-
QUERY: 'QUERY' as const,
7-
MUTATION: 'MUTATION' as const,
8-
SUBSCRIPTION: 'SUBSCRIPTION' as const,
9-
FIELD: 'FIELD' as const,
10-
FRAGMENT_DEFINITION: 'FRAGMENT_DEFINITION' as const,
11-
FRAGMENT_SPREAD: 'FRAGMENT_SPREAD' as const,
12-
INLINE_FRAGMENT: 'INLINE_FRAGMENT' as const,
13-
VARIABLE_DEFINITION: 'VARIABLE_DEFINITION' as const,
14-
FRAGMENT_VARIABLE_DEFINITION: 'FRAGMENT_VARIABLE_DEFINITION' as const,
15-
/** Type System Definitions */
16-
SCHEMA: 'SCHEMA' as const,
17-
SCALAR: 'SCALAR' as const,
18-
OBJECT: 'OBJECT' as const,
19-
FIELD_DEFINITION: 'FIELD_DEFINITION' as const,
20-
ARGUMENT_DEFINITION: 'ARGUMENT_DEFINITION' as const,
21-
INTERFACE: 'INTERFACE' as const,
22-
UNION: 'UNION' as const,
23-
ENUM: 'ENUM' as const,
24-
ENUM_VALUE: 'ENUM_VALUE' as const,
25-
INPUT_OBJECT: 'INPUT_OBJECT' as const,
26-
INPUT_FIELD_DEFINITION: 'INPUT_FIELD_DEFINITION' as const,
27-
DIRECTIVE_DEFINITION: 'DIRECTIVE_DEFINITION' as const,
28-
} as const;
29-
// eslint-disable-next-line @typescript-eslint/no-redeclare
7+
export * as DirectiveLocation from './directiveLocation_.ts';
8+
309
export type DirectiveLocation =
31-
(typeof DirectiveLocation)[keyof typeof DirectiveLocation];
10+
(typeof DirectiveLocation_)[keyof typeof DirectiveLocation_];

src/language/directiveLocation_.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/* eslint-disable @typescript-eslint/no-redeclare */
2+
3+
/** Request Definitions */
4+
export const QUERY = 'QUERY';
5+
export type QUERY = typeof QUERY;
6+
export const MUTATION = 'MUTATION';
7+
export type MUTATION = typeof MUTATION;
8+
export const SUBSCRIPTION = 'SUBSCRIPTION';
9+
export type SUBSCRIPTION = typeof SUBSCRIPTION;
10+
export const FIELD = 'FIELD';
11+
export type FIELD = typeof FIELD;
12+
export const FRAGMENT_DEFINITION = 'FRAGMENT_DEFINITION';
13+
export type FRAGMENT_DEFINITION = typeof FRAGMENT_DEFINITION;
14+
export const FRAGMENT_SPREAD = 'FRAGMENT_SPREAD';
15+
export type FRAGMENT_SPREAD = typeof FRAGMENT_SPREAD;
16+
export const INLINE_FRAGMENT = 'INLINE_FRAGMENT';
17+
export type INLINE_FRAGMENT = typeof INLINE_FRAGMENT;
18+
export const VARIABLE_DEFINITION = 'VARIABLE_DEFINITION';
19+
export type VARIABLE_DEFINITION = typeof VARIABLE_DEFINITION;
20+
export const FRAGMENT_VARIABLE_DEFINITION = 'FRAGMENT_VARIABLE_DEFINITION';
21+
export type FRAGMENT_VARIABLE_DEFINITION = typeof FRAGMENT_VARIABLE_DEFINITION;
22+
23+
/** Type System Definitions */
24+
export const SCHEMA = 'SCHEMA';
25+
export type SCHEMA = typeof SCHEMA;
26+
export const SCALAR = 'SCALAR';
27+
export type SCALAR = typeof SCALAR;
28+
export const OBJECT = 'OBJECT';
29+
export type OBJECT = typeof OBJECT;
30+
export const FIELD_DEFINITION = 'FIELD_DEFINITION';
31+
export type FIELD_DEFINITION = typeof FIELD_DEFINITION;
32+
export const ARGUMENT_DEFINITION = 'ARGUMENT_DEFINITION';
33+
export type ARGUMENT_DEFINITION = typeof ARGUMENT_DEFINITION;
34+
export const INTERFACE = 'INTERFACE';
35+
export type INTERFACE = typeof INTERFACE;
36+
export const UNION = 'UNION';
37+
export type UNION = typeof UNION;
38+
export const ENUM = 'ENUM';
39+
export type ENUM = typeof ENUM;
40+
export const ENUM_VALUE = 'ENUM_VALUE';
41+
export type ENUM_VALUE = typeof ENUM_VALUE;
42+
export const INPUT_OBJECT = 'INPUT_OBJECT';
43+
export type INPUT_OBJECT = typeof INPUT_OBJECT;
44+
export const INPUT_FIELD_DEFINITION = 'INPUT_FIELD_DEFINITION';
45+
export type INPUT_FIELD_DEFINITION = typeof INPUT_FIELD_DEFINITION;
46+
export const DIRECTIVE_DEFINITION = 'DIRECTIVE_DEFINITION';
47+
export type DIRECTIVE_DEFINITION = typeof DIRECTIVE_DEFINITION;

src/language/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,8 @@ export {
124124
isSubscriptionOperationDefinitionNode,
125125
} from './predicates.ts';
126126

127+
// @see https://github.com/typescript-eslint/typescript-eslint/issues/10313
128+
// Deno misclassifies this merged value+type re-export and requires `export type`.
129+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
130+
// @ts-ignore TS1205
127131
export { DirectiveLocation } from './directiveLocation.ts';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* eslint-disable no-unused-expressions */
2+
import { describe, it } from 'node:test';
3+
4+
import { TypeKind } from '../index.ts';
5+
6+
describe('TypeKind', () => {
7+
it('is a term level namespace with term level enum members', () => {
8+
const a: TypeKind.SCALAR = TypeKind.SCALAR;
9+
a;
10+
const b: TypeKind = TypeKind.SCALAR;
11+
b;
12+
const c: TypeKind = TypeKind.NON_NULL;
13+
c;
14+
});
15+
16+
it('is a type level namespace with type level enum members', () => {
17+
// @ts-expect-error
18+
const a: TypeKind.SCALAR = 'bad';
19+
a;
20+
const b: TypeKind.SCALAR = 'SCALAR';
21+
b;
22+
// @ts-expect-error
23+
const c: TypeKind = 'bad';
24+
c;
25+
const d: TypeKind = 'SCALAR';
26+
d;
27+
const e: TypeKind = 'NON_NULL';
28+
e;
29+
});
30+
});

src/type/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,18 @@ export {
191191
__InputValue,
192192
__EnumValue,
193193
__TypeKind,
194-
// "Enum" of Type Kinds
195-
TypeKind,
196194
// Meta-field definitions.
197195
SchemaMetaFieldDef,
198196
TypeMetaFieldDef,
199197
TypeNameMetaFieldDef,
200198
} from './introspection.ts';
201199

200+
// @see https://github.com/typescript-eslint/typescript-eslint/issues/10313
201+
// Deno misclassifies this merged value+type re-export and requires `export type`.
202+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
203+
// @ts-ignore TS1205
204+
export { TypeKind } from './typeKind.ts';
205+
202206
// Validate GraphQL schema.
203207
export { validateSchema, assertValidSchema } from './validate.ts';
204208

src/type/introspection.ts

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ import {
3232
import type { GraphQLDirective } from './directives.ts';
3333
import { GraphQLBoolean, GraphQLString } from './scalars.ts';
3434
import type { GraphQLSchema } from './schema.ts';
35+
import { TypeKind } from './typeKind.ts';
36+
37+
// @see https://github.com/typescript-eslint/typescript-eslint/issues/10313
38+
// Deno misclassifies this merged value+type re-export and requires `export type`.
39+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
40+
// @ts-ignore TS1205
41+
export { TypeKind } from './typeKind.ts';
3542

3643
export const __Schema: GraphQLObjectType = new GraphQLObjectType({
3744
name: '__Schema',
@@ -478,20 +485,6 @@ export const __EnumValue: GraphQLObjectType = new GraphQLObjectType({
478485
}) as GraphQLFieldConfigMap<GraphQLEnumValue, unknown>,
479486
});
480487

481-
export const TypeKind = {
482-
SCALAR: 'SCALAR' as const,
483-
OBJECT: 'OBJECT' as const,
484-
INTERFACE: 'INTERFACE' as const,
485-
UNION: 'UNION' as const,
486-
ENUM: 'ENUM' as const,
487-
INPUT_OBJECT: 'INPUT_OBJECT' as const,
488-
LIST: 'LIST' as const,
489-
NON_NULL: 'NON_NULL' as const,
490-
} as const;
491-
492-
// eslint-disable-next-line @typescript-eslint/no-redeclare
493-
export type TypeKind = (typeof TypeKind)[keyof typeof TypeKind];
494-
495488
export const __TypeKind: GraphQLEnumType = new GraphQLEnumType({
496489
name: '__TypeKind',
497490
description: 'An enum describing what kind of type a given `__Type` is.',

src/type/typeKind.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* eslint-disable import/no-namespace */
2+
import type * as TypeKind_ from './typeKind_.ts';
3+
4+
/**
5+
* The set of allowed introspection type kind values.
6+
*/
7+
export * as TypeKind from './typeKind_.ts';
8+
9+
export type TypeKind = (typeof TypeKind_)[keyof typeof TypeKind_];

src/type/typeKind_.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* eslint-disable @typescript-eslint/no-redeclare */
2+
3+
export const SCALAR = 'SCALAR';
4+
export type SCALAR = typeof SCALAR;
5+
export const OBJECT = 'OBJECT';
6+
export type OBJECT = typeof OBJECT;
7+
export const INTERFACE = 'INTERFACE';
8+
export type INTERFACE = typeof INTERFACE;
9+
export const UNION = 'UNION';
10+
export type UNION = typeof UNION;
11+
export const ENUM = 'ENUM';
12+
export type ENUM = typeof ENUM;
13+
export const INPUT_OBJECT = 'INPUT_OBJECT';
14+
export type INPUT_OBJECT = typeof INPUT_OBJECT;
15+
export const LIST = 'LIST';
16+
export type LIST = typeof LIST;
17+
export const NON_NULL = 'NON_NULL';
18+
export type NON_NULL = typeof NON_NULL;

0 commit comments

Comments
 (0)