The README below is currently out of date with the specifics of how ts-gql works and how to use it. It will be updated soon.
Write GraphQL queries in TypeScript and generate types effortlessly
There are lots of great tools(some of which ts-gql use internally!) for generating types from GraphQL Queries though a lot of the solutions have at least one of two problems
- The writing of a query isn't connected to the type that it returns
- You're forced to write queries in
.graphql
files rather than inline- This also often means that you can't use fragments or that there's a new import syntax to learn
When using ts-gql, you write GraphQL queries with a tagged template literal like normal.
import { gql } from "@ts-gql/tag";
let myQuery = gql`
query MyQuery {
hello
}
`;
And then our ESLint plugin will auto-fix it to
import { gql } from "@ts-gql/tag";
let myQuery = gql`
query MyQuery {
hello
}
`("MyQuery");
It will also generate a file at __generated__/ts-gql/MyQuery.d.ts
/*
ts-gql-meta-begin
{
"hash": "1b2c07ec819c249efde9717f714dcac4",
"filename": "../../pages/index.tsx",
"partial": "query MyQuery"
}
ts-gql-meta-end
*/
import * as SchemaTypes from "./@schema";
type MyQueryQueryVariables = {};
type MyQueryQuery = { readonly __typename: "Query" } & Pick<
SchemaTypes.Query,
"hello"
>;
declare module "@ts-gql/tag" {
interface Documents {
MyQuery: {
document: "\n query MyQuery {\n hello\n }\n\n";
type: "query";
result: MyQueryQuery;
variables: undefined;
};
}
}
You'll have the best experience if you have ESLint auto fix on save enabled in your editor.
Why do we need to add `("MyQuery")`?
TypeScript doesn't currently type tagged template literals with literal string types so we have to add ("MyQuery")
though there are issues discussing it which would remove the need for this.
What this means is that behind the scenes myQuery
will be typed as
type MyQuery = {
___type: {
type: "query";
document: "\n query MyQuery {\n hello\n }\n";
result: { hello: string };
};
};
You can then use @ts-gql/apollo
or @ts-gql/urql
to augment the types of GraphQL libraries so that they will type their results and query variables based on your query.
When using ts-gql, you'll always need @ts-gql/tag
and @ts-gql/eslint-plugin
.
yarn add graphql @ts-gql/tag @ts-gql/eslint-plugin
If you're not already using ESLint and @typescript-eslint/parser
, you'll need those too.
You'll need to configure ESLint like this.
module.exports = {
parser: "@typescript-eslint/parser",
parserOptions: {
project: "tsconfig.json",
},
plugins: ["@ts-gql"],
rules: {
"@ts-gql/ts-gql": [
"error",
{
schemaFilename: require("path").join(__dirname, "schema.graphql"),
generatedDirectory: require("path").join(
__dirname,
"__generated__",
"ts-gql"
),
},
],
},
};
Note: you should have your GraphQL schema written at
schema.graphql
. You can also have aschema.json
with the result of an introspection query.
Note: ts-gql only supports
@apollo/client
(Apollo client version 3)
yarn add @ts-gql/apollo
Add an import of @ts-gql/apollo
somewhere in your app.
You can now use useQuery
and etc. with queries created with @ts-gql/tag
.
yarn add @ts-gql/urql
Add an import of @ts-gql/urql
somewhere in your app.
You can now use useQuery
and etc. with queries created with @ts-gql/tag
.
- Offer the option to use hashes instead of document names so document names don't have to be unique
- Autofix not specifying a variable in an operation
- A Babel plugin/some kind of build time transform that performs optimisations like the Relay Compiler does
- This should be relatively easy since every operation must be entirely static since the only kind of interpolations allowed will be fragment interpolations and we'll know the contents of the fragment because it's encoded in the type.]
- Fix types being out of date in editors so types can't be generated for operations with fragments
- Improve the experience of creating GraphQL APIs, Nexus does a really great job of this
- graphql-code-generator for the infrastructure to generate TypeScript types from GraphQL queries
- graphql-let for providing a really nice experience