gql.tada

1.9.2 · active · verified Wed Apr 22

gql.tada is a powerful and spec-compliant GraphQL document authoring library designed for TypeScript environments. Its primary function is to infer the result and variables types of GraphQL queries, mutations, and fragments directly within the TypeScript type system, eliminating the need for separate code generation steps. Currently at version 1.9.2, the library maintains an active development pace with frequent patch and minor releases, as evidenced by recent changelogs. A key differentiator is its deep integration with TypeScript, providing on-the-fly type safety, editor feedback, and auto-completion without external build steps, especially when paired with a language server like GraphQLSP. It achieves this by parsing GraphQL documents directly in TypeScript, deriving a schema from introspection and scalar configuration, and then mapping these definitions to robust result and variables types, including advanced features like fragment masks and gradual fragment unwrapping.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates defining GraphQL fragments and queries using the `graphql` tagged template literal, inferring result and fragment types with `typeof` and `FragmentOf`, and safely accessing data.

import { graphql } from 'gql.tada';
import type { FragmentOf } from 'gql.tada';

// Ensure you have configured gql.tada via its CLI (e.g., `npx gql-tada init` and `npx gql-tada generate`)
// and have a 'graphql-env.d.ts' file at your project root or as specified in tsconfig.
// This setup allows TypeScript to understand the `graphql` tagged template literal
// and infer types from your GraphQL schema.

// Define a GraphQL fragment for reusable fields
const userFragment = graphql(`
  fragment UserProfile on User {
    id
    name
    email
  }
`);

// Define a GraphQL query that incorporates the fragment
const viewerQuery = graphql(`
  query Viewer {
    viewer {
      ...UserProfile
      status
    }
  }
  ${userFragment} // Fragments must be included in the document
`);

// Infer the TypeScript type of the query result
type ViewerQueryResult = typeof viewerQuery;
// Expected type: { viewer: { id: string, name: string, email: string, status: string | null } | null }

// Infer the TypeScript type of the fragment
type UserProfileType = FragmentOf<typeof userFragment>;
// Expected type: { id: string, name: string, email: string }

// Example function to process query results with type safety
function displayViewerData(data: ViewerQueryResult) {
  if (data?.viewer) {
    // Directly access fields, including those from the fragment
    console.log(`Viewer ID: ${data.viewer.id}`);
    console.log(`Viewer Name: ${data.viewer.name}`);
    console.log(`Viewer Email: ${data.viewer.email}`);
    console.log(`Viewer Status: ${data.viewer.status ?? 'N/A'}`);
  } else {
    console.log("No viewer data available.");
  }
}

// Mock data for demonstration purposes
const mockData: ViewerQueryResult = {
  viewer: {
    id: "user-123",
    name: "Alice Wonderland",
    email: "alice@example.com",
    status: "active"
  }
};

displayViewerData(mockData);

// Example of a component prop type using a fragment
interface UserCardProps {
  user: UserProfileType; // Type-safe prop based on the fragment
}

const UserCard = ({ user }: UserCardProps) => {
  return `<div class="user-card"><h2>${user.name}</h2><p>Email: ${user.email}</p></div>`;
};

// Usage of the UserCard component
if (mockData.viewer) {
  const cardHtml = UserCard({ user: mockData.viewer });
  console.log(cardHtml);
}

view raw JSON →