3

GraphQL Code Generator creates this type on the top of the created TypeScript file:

export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };

and uses it for all client created query variables:

src/foo.graphql:

query Foo($id: ID!) {
  foo(id: $id) {
    bar
  }
}

generated/foo.ts:

...

export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };

...

export type FooQueryVariables = Exact<{
  id: Scalars['ID'];
}>;

...

What is the purpose of this Exact<T> type and how does it affect FooQueryVariables (vs. if it would not be there)?


Full demo for https://www.graphql-code-generator.com/#live-demo:

schema.graphql:

schema {
  query: Query
}

type Query {
  foo(id: ID!): Foo
}

type Foo {
  bar: String!
}

operation.graphql:

query Foo($id: ID!) {
  foo(id: $id) {
    bar
  }
}

codegen.yml:

generates:
  operations-types.ts:
    plugins:
      - typescript
      - typescript-operations

Generated operations-types.ts:

export type Maybe<T> = T | null;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
};

export type Query = {
  __typename?: 'Query';
  foo?: Maybe<Foo>;
};


export type QueryFooArgs = {
  id: Scalars['ID'];
};

export type Foo = {
  __typename?: 'Foo';
  bar: Scalars['String'];
};

export type FooQueryVariables = Exact<{
  id: Scalars['ID'];
}>;


export type FooQuery = { __typename?: 'Query', foo?: Maybe<{ __typename?: 'Foo', bar: string }> };
ruohola
  • 21,987
  • 6
  • 62
  • 97
  • 2
    It fully "expands" types (which provides better hinting in the code editor). Consider `type A = { a: number; }; type B = { b: string; }; type C = A & B;`... if you hover type `C` you'll see `A & B` in the intellisense. If you hover `CE` in `type CE = Exact`, you'll see `{ a: number; b: string; }`. I'll leave it to someone else as to why this happens. See https://www.typescriptlang.org/play?#code/C4TwDgpgBAglC8UDeUCGAuKA7ArgWwCMIAnAbigF9yAoUSKAIQWSgMwGdhiBLLAc3JUotcNADCzOADJGpEfQCiAD1QBjYAB4AKlAhLgELABN2LANoBrCCA5defALqYcWC1gD2AdyyUAfMxQzAGkoXigrEHcAMygtJ1jgh0o5OnEFZmU1TTFfOSA – spender Sep 21 '21 at 12:03

1 Answers1

5

It aims to make it so that one cannot pass an object with any additional properties (in addition to id) as FooQueryVariables. But it fails to do so: https://github.com/dotansimha/graphql-code-generator/issues/4577

ruohola
  • 21,987
  • 6
  • 62
  • 97