Build Typed GraphQL Queries
typed-graphqlify is a TypeScript library designed to streamline the process of building GraphQL queries by providing a single source of truth for both the GraphQL query structure and its corresponding TypeScript types. It eliminates the common problem of redundancy found in many GraphQL client setups where developers must define a GraphQL query string and then separately define a matching TypeScript interface. The library, currently at version 3.1.6, generally sees minor updates every few weeks to months, focusing on dependency updates and minor feature enhancements. Its core differentiator lies in its ability to generate GraphQL query strings and strong TypeScript types directly from a GraphQL-like JavaScript object structure, using dedicated `types` helpers for scalar and optional fields. It primarily acts as a query builder, providing the necessary string for execution, but does not handle the network request itself, integrating seamlessly with existing GraphQL clients like Apollo or Relay for actual data fetching.
Common errors
-
Argument of type 'GraphQLQuery<...>' is not assignable to parameter of type 'string'.
cause Attempting to pass the `typed-graphqlify` query object directly to a GraphQL execution client method that expects a raw GraphQL query string.fixCall the `.toString()` method on your generated query object to convert it into a GraphQL string: `executeGraphql(myQuery.toString())`. -
Property 'data' does not exist on type 'GraphQLQuery<...>'
cause Incorrectly trying to directly access `data` property on the `typed-graphqlify` query builder object for type inference.fixTo infer the type of the GraphQL response data, use `typeof myQuery.data` (e.g., `const result: typeof myQuery.data = ...`). The `.data` property is a type-only construct. -
Cannot find name 'query'. (or 'types', 'alias')
cause The necessary functions or objects (`query`, `types`, `alias`) were not imported from the `typed-graphqlify` package.fixEnsure you have correctly imported the required symbols using named imports: `import { query, types, alias } from 'typed-graphqlify';`.
Warnings
- gotcha typed-graphqlify functions as a GraphQL query builder and type generator, not a full-fledged GraphQL client. It generates the GraphQL query string and corresponding TypeScript types, but you must use a separate library (e.g., Apollo Client, `fetch`) to execute the generated query string against a GraphQL endpoint.
- gotcha The `types` helper object (e.g., `types.number`, `types.optional.string`, `types.oneOf`) is crucial for defining the correct GraphQL scalar, optional, and enum types within your query object. Incorrectly using these helpers or omitting them can lead to generated GraphQL strings that do not match your backend schema or incorrect TypeScript type inference.
- deprecated When defining enum fields, the README mentions `types.enum` is deprecated. Users should instead use `types.oneOf` with an array or plain object for better type inference and compatibility.
Install
-
npm install typed-graphqlify -
yarn add typed-graphqlify -
pnpm add typed-graphqlify
Imports
- query
const query = require('typed-graphqlify').queryimport { query } from 'typed-graphqlify' - types
import types from 'typed-graphqlify'
import { types } from 'typed-graphqlify' - alias
import { Alias } from 'typed-graphqlify'import { alias } from 'typed-graphqlify' - mutation
import { mutation } from 'typed-graphqlify'
Quickstart
import { query, types } from 'typed-graphqlify';
// Mock an execution function for demonstration purposes
async function executeGraphql<T>(graphqlQuery: string): Promise<T> {
console.log('Executing GraphQL query:\n', graphqlQuery);
// In a real application, this would make an actual network request
// to your GraphQL endpoint (e.g., using fetch, axios, or a GraphQL client).
// For this example, we'll return a mock data structure that matches the
// query's expected type, simulating a successful response.
return Promise.resolve({
user: {
id: 123,
name: 'John Doe',
bankAccount: {
id: 456,
branch: 'Main Branch', // Or undefined if optional and not present
},
},
} as T);
}
// Define a GraphQL query using typed-graphqlify's DSL
const getUserQuery = query('GetUser', {
user: {
id: types.number,
name: types.string,
bankAccount: {
id: types.number,
branch: types.optional.string, // Define 'branch' as an optional string
},
},
});
console.log('Generated GraphQL Query:\n', getUserQuery.toString());
// Execute the GraphQL query and infer the result type safely
const data: typeof getUserQuery.data = await executeGraphql(getUserQuery.toString());
console.log('Received data:', data);
// Demonstrate type-safety: 'data' is strongly typed based on the query definition
console.log(`User ID: ${data.user.id}`);
console.log(`User Name: ${data.user.name}`);
if (data.user.bankAccount.branch) {
console.log(`Bank Branch: ${data.user.bankAccount.branch}`);
} else {
console.log('Bank Branch: Not provided');
}