Skip to content

Commit d6be64c

Browse files
Add 'TypedQueryDocumentNode' TS type (#2749)
1 parent b83a9fe commit d6be64c

File tree

4 files changed

+46
-2
lines changed

4 files changed

+46
-2
lines changed

integrationTests/ts/index.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import { parse } from 'graphql/language';
12
import { GraphQLString, GraphQLSchema, GraphQLObjectType } from 'graphql/type';
2-
import { ExecutionResult } from 'graphql/execution';
3-
import { graphqlSync } from 'graphql';
3+
import { ExecutionResult, execute } from 'graphql/execution';
4+
import { TypedQueryDocumentNode, graphqlSync } from 'graphql';
45

56
interface SomeExtension {
67
number: number;
@@ -69,3 +70,28 @@ const result: ExecutionResult = graphqlSync({
6970
`,
7071
variableValues: { who: 'Dolly' },
7172
});
73+
74+
// Tests for TS specific TypedQueryDocumentNode type
75+
const queryDocument = parse(`
76+
query helloWho($who: String){
77+
test(who: $who)
78+
}
79+
`);
80+
81+
type ResponseData = { test: string };
82+
const typedQueryDocument = queryDocument as TypedQueryDocumentNode<
83+
ResponseData,
84+
{}
85+
>;
86+
87+
// Supports conversion to DocumentNode
88+
execute({ schema, document: typedQueryDocument });
89+
90+
function wrappedExecute<T>(document: TypedQueryDocumentNode<T>) {
91+
return execute({ schema, document }) as ExecutionResult<T>;
92+
}
93+
94+
const { data } = wrappedExecute(typedQueryDocument);
95+
if (data != null) {
96+
const typedData: ResponseData = data;
97+
}

src/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,4 +461,5 @@ export {
461461
BuildSchemaOptions,
462462
BreakingChange,
463463
DangerousChange,
464+
TypedQueryDocumentNode,
464465
} from './utilities/index';

src/utilities/index.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,8 @@ export {
112112
DangerousChange,
113113
} from './findBreakingChanges';
114114

115+
// Wrapper type that contains DocumentNode and types that can be deduced from it.
116+
export { TypedQueryDocumentNode } from './typedQueryDocumentNode';
117+
115118
// @deprecated: Report all deprecated usage within a GraphQL document.
116119
export { findDeprecatedUsages } from './findDeprecatedUsages';
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { DocumentNode, ExecutableDefinitionNode } from '../language/ast';
2+
3+
/**
4+
* Wrapper type that contains DocumentNode and types that can be deduced from it.
5+
*/
6+
interface TypedQueryDocumentNode<
7+
TResponseData = Record<string, any>,
8+
TRequestVariables = Record<string, any>
9+
> extends DocumentNode {
10+
readonly definitions: ReadonlyArray<ExecutableDefinitionNode>;
11+
// FIXME: remove once TS implements proper way to enforce nominal typing
12+
readonly __enforceStructuralTypingOnResponseDataType?: TResponseData;
13+
readonly __enforceStructuralTypingOnRequestVariablesType?: TRequestVariables;
14+
}

0 commit comments

Comments
 (0)