Skip to content

gql.tada API ​

Functions ​

graphql() ​

Description
input argumentA string of a GraphQL document.
fragments argumentAn optional list of other GraphQL fragments created with this function.
returnsA GraphQL DocumentNode with result and variables types.

Creates a DocumentNode with result and variables types.

You can compose fragments into this function by passing them and a fragment mask will be created for them. When creating queries, the returned document of queries can be passed into GraphQL clients which will then automatically infer the result and variables types.

It is used with your schema in setupSchema to create a result type of your queries, fragments, and variables. If you instead would like to manually create a graphql function with an explicit schema type, use initGraphQLTada instead.

Example ​

ts
import { 
graphql
} from 'gql.tada';
const
fragment
=
graphql
(`
fragment HelloWorld on Query { hello world } `); const
query
=
graphql
(
` query HelloQuery { hello ...HelloWorld } `, [
fragment
]
);

graphql.scalar() ​

Description
name argumentA name of a GraphQL scalar or enum.
value argumentThe value to be type-checked against the type.
returnsThe value will be returned directly.

Type checks a given input value to be of a scalar or enum type and returns the value directly.

You can use this utility to add a type check for a scalar or enum value, or to retrieve the type of a scalar or enum. This is useful if you’re writing a function or component that only accepts a scalar or enum, but not a full fragment.

NOTE

It’s not recommended to use this utiliy to replace fragments, i.e. to create your own object types. Try to use fragments where appropriate instead.

Example ​

ts
import { 
graphql
} from 'gql.tada';
function
validateMediaEnum
(
value
: 'Book' | 'Song' | 'Video') {
const
media
=
graphql
.
scalar
('Media',
value
);
} type
Media
=
ReturnType
<typeof
graphql
.
scalar
<'Media'>>;

graphql.persisted() ​

Description
hash argumentA hash associated with this query.
document optional argumentOptionally, the document, if it's supposed to be accessible during runtime.

Generates a faux-document containing a property called documentId which can be used to send off queries as Persisted Operations.

We must either pass the document as a generic type argument or as the second argument:

  • graphql.persisted<typeof document>("abc...")
  • graphql.persisted("abc...", document)

The TypeScript plugin and the gql-tada check command run a diagnostic which can check that the document is passed into graphql.persisted() correctly. Furthermore, the TypeScript plugin offers a code action to automatically update the hash argument to a SHA256-hash computed from the document.

This is useful to implement and extract persisted operations using the CLI. Additionally, when the document is passed as a generic — as long as our GraphQL cache supports this — it can be fully omitted during runtime from the client-side bundle.

Client Compatibility

When passing a document by type as a generic to graphql.persisted<typeof document>("..."), your runtime code won’t see any definitions on the AST.

This may cause problems with GraphQL clients (especially normalized caches) that rely on the AST to be available, since the full document will be transpile away. For such clients, you may want to preserve the document by passing it as a second argument instead.

Example ​

ts
import { 
graphql
} from 'gql.tada';
const
query
=
graphql
(`
query Hello { hello } `); // You can now use this in your `useQuery` calls. const
persistedOperation
=
graphql
.
persisted
<typeof
query
>('sha256:x');

readFragment() ​

Description
_document optional argumentA GraphQL document of a fragment, created using graphql().
fragment argumentA mask of the fragment, which can be wrapped in arrays, or nullable.
returnsThe unmasked data of the fragment.

When graphql() is used to create a fragment and is spread into another fragment or query, their result types will only contain a “reference” to the fragment. This encourages isolation and is known as “fragment masking.”

This means that you must use readFragment() to unmask these fragment masks and get to the data. This encourages isolation and only using the data you define a part of your codebase to require:

ts
const unmaskedData = readFragment(Fragment, maskedData);

When passing fragment masks to readFragment(), you may also pass nullable, optional data, or data wrapped in arrays to readFragment() and the result type will be unwrapped and inferred accordingly.

Instead of passing the fragment document as the first argument, you may also pass it as a generic, since it's not used as a runtime value anyway:

ts
const unmaskedData = readFragment<typeof Fragment>(maskedData);
Learn more about fragment masking

Example ​

ts
import { 
FragmentOf
,
ResultOf
,
graphql
,
readFragment
} from 'gql.tada';
const
pokemonItemFragment
=
graphql
(`
fragment PokemonItem on Pokemon { id name } `); const
getPokemonItem
= (
data
:
FragmentOf
<typeof
pokemonItemFragment
> | null) => {
// @annotate: Unmasks the fragment and casts to the result type: const
pokemon
=
readFragment
(
pokemonItemFragment
,
data
);
}; const
pokemonQuery
=
graphql
(
` query Pokemon($id: ID!) { pokemon(id: $id) { id ...PokemonItem } } `, [
pokemonItemFragment
]
); const
getQuery
= (
data
:
ResultOf
<typeof
pokemonQuery
>) => {
getPokemonItem
(
data
.
pokemon
);
};

maskFragments() ​

Description
_fragments argumentA list of GraphQL documents of fragments, created using graphql().
data argumentThe combined result data of the fragments, which can be wrapped in arrays.
returnsThe masked data of the fragments.

NOTE

While useful, maskFragments() is mostly meant to be used in tests or as an escape hatch to convert data to masked fragments.

You shouldn’t have to use it in your regular component code.

When graphql() is used to compose fragments into another fragment or operation, the resulting type will by default be masked, unless the @_unmask directive is used.

This means that when we’re writing tests or are creating “fake data” without inferring types from a full document, the types in TypeScript may not match, since our testing data will not be masked and will be equal to the result type of the fragments.

To address this, the maskFragments utility takes a list of fragments and masks data (or an array of data) to match the masked fragment types of the fragments.

Example ​

ts
import { 
graphql
,
maskFragments
} from 'gql.tada';
const
pokemonItemFragment
=
graphql
(`
fragment PokemonItem on Pokemon { id name } `); const
data
=
maskFragments
([
pokemonItemFragment
], {
id
: '001',
name
: 'Bulbasaur',
});

unsafe_readResult() ​

Description
_document argumentA GraphQL document, created using graphql().
data argumentThe result data of the GraphQL document with optional fragment refs.
returnsThe masked result data of the document.

CAUTION

Unlike, maskFragments(), this utility is unsafe, and should only be used when you know that data matches the expected shape of a GraphQL query you created.

While useful, this utility is only a slightly safer alternative to as any and doesn’t type check the result shape against the masked fragments in your document.

You shouldn’t have to use it in your regular app code.

When graphql() is used to compose fragments into a document, the resulting type will by default be masked, unless the @_unmask directive is used.

This means that when we’re writing tests and are creating “fake data”, for instance for a query, that we cannot convert this data to the query’s result type, if it contains masked fragment refs.

To address this, the unsafe_readResult utility accepts the document and converts a query’s data to masked data.

Example ​

ts
import { 
graphql
,
unsafe_readResult
} from 'gql.tada';
const
pokemonItemFragment
=
graphql
(`
fragment PokemonItem on Pokemon { id name } `); const
query
=
graphql
(
` query { pokemon(id: "001") { ...PokemonItem } } `, [
pokemonItemFragment
]
);
data will be cast (unsafely!) to the result type
const
data
=
unsafe_readResult
(
query
, {
pokemon
: {
id
: '001',
name
: 'Bulbasaur' },
});

initGraphQLTada() ​

Description
Setup genericAn AbstractSetupSchema configuration object
returnsA typed graphql() function.

initGraphQLTada accepts an AbstractSetupSchema configuration object as a generic and returns a graphql() function that may be used to create documents typed using your GraphQL schema.

You should use and re-export the resulting function named as graphql or gql for your editor and the TypeScript language server to recognize your GraphQL documents correctly.

Installation

Learn how to use initGraphQLTada()

Example ​

ts
import { 
initGraphQLTada
} from 'gql.tada';
import type {
introspection
} from './graphql/graphql-env.d.ts';
export const
graphql
=
initGraphQLTada
<{
introspection
:
introspection
;
scalars
: {
DateTime
: string;
Json
: any;
}; }>(); const
query
=
graphql
(`
{ __typename } `);

Types ​

ResultOf ​

Description
Document genericThe document type of a DocumentNode carrying the result type.

This accepts a TadaDocumentNode and returns the attached Result type of GraphQL documents.


VariablesOf ​

Description
Document genericThe document type of a DocumentNode carrying the variables type.

This accepts a TadaDocumentNode and returns the attached Variables type of GraphQL documents.


FragmentOf ​

Description
Document genericA DocumentNode containing a fragment definition.

Creates a fragment mask for a given fragment document.

When graphql() is used to create a fragment and is spread into another fragment or query, their result types will only contain a “reference” to the fragment. This encourages isolation and is known as “fragment masking.”

While readFragment() is used to unmask these fragment masks, this utility creates a fragment mask, so you can accept the masked data in the part of your codebase that defines a fragment.

Learn more about fragment masking

Example ​

ts
import { 
FragmentOf
,
graphql
,
readFragment
} from 'gql.tada';
const
pokemonItemFragment
=
graphql
(`
fragment PokemonItem on Pokemon { id name } `); // May be called with any data that contains the mask const
getPokemonItem
= (
data
:
FragmentOf
<typeof
pokemonItemFragment
>) => {
// Unmasks the fragment and casts to the result type const
pokemon
=
readFragment
(
pokemonItemFragment
,
data
);
};

TadaDocumentNode ​

Description
Result genericThe type of GraphQL results, as returned by GraphQL APIs for a given query.
Variables genericThe type of variables, as accepted by GraphQL APIs for a given query.

A GraphQL DocumentNode with attached types for results and variables.

This is a GraphQL DocumentNode with attached types for results and variables. This is used by GraphQL clients to infer the types of results and variables and provide type-safety in GraphQL documents.

You can create typed GraphQL documents using the graphql() function.


setupSchema ​

You may extend this interface via declaration merging with your IntrospectionQuery data and optionally your scalars to get proper type inference. This is done by declaring a declaration for it as per the following example.

Configuring scalars is optional and by default the standard scalrs are already defined.

This will configure the default graphql() export to infer types from your schema. Alternatively, if you don’t want to define your schema project-wide, you may call initGraphQLTada() instead.

Read more about setting up your schema on the “Installation” page.

Example ​

ts
import type { 
introspection
} from './graphql/graphql-env.d.ts';
declare module 'gql.tada' { interface setupSchema {
introspection
:
introspection
;
scalars
: {
DateTime
: string;
Json
: any;
}; } }

AbstractSetupSchema ​

Description
introspection propertyIntrospection of your schema in the IntrospectionQuery format.
scalars propertyAn optional object type with scalar names as keys and the corresponding scalar types as values.
disableMasking flagThis may be set to true to disable fragment masking globally.

This is used either via setupSchema or initGraphQLTada() to set up your schema and scalars. Your configuration objects must match the shape of this type.

The scalars option is optional and can be used to set up custom scalar and enum types. It must be an object map of scalar names to their desired TypeScript types. When a scalar or enum is missing in your custom scalars object, a fallback will be used for the built-in scalars (Int, Float, String, Boolean, and ID) and for enums, the enumValues defined by the schema will be used.

The disableMasking flag may be set to true instead of using @_unmask on individual fragments and allows fragment masking to be disabled globally.