7

Edit: I'm looking for an authority and sourced answer from Graphql-Angular community to provide a best practice example.

For example, we have a Person type defined as such in TypeScript:

interface Person {
  firstName: string;
  lastName: string;
  birthDate: Date;
  age: number;
  ...and many more attributes
}

Let's say you have a component, and in accordance to the graphql mantra, you only fetch what you need. No overfetching and underfetching.

I only need the Person's firstName and age, so I make that in my Apollo Query.

Now, how do I type this Object that I just fetched?

The structure is a partial of Person, so I'm inclined to simply do Partial<Person>. This makes all the attributes declared on Person optional.

But that's not what's going on here. We're pulling a partial of Person with only age and firstName. That's it.

Is there no other way to type this correctly other than making another interface like:

interace MyComponentPerson {
  firstName: string;
  age: number;
}

Is there an official style guide / way to do this? I've asked on their slack and not getting answers. Looked on the docs as well didn't see anything about this.

Ka Mok
  • 1,937
  • 3
  • 22
  • 47
  • as for me - i don't even have a full person (e.g.) type - i have only what i need and if i need it in different forms i have a type for each form (possibly inherited) – Pavel Agarkov Aug 23 '18 at 20:33
  • Yeah that's what I mean by there's a lot of ways to do it, and I wanted to hear from a authority figure as to what the best practice is. – Ka Mok Aug 23 '18 at 20:45

2 Answers2

3

You could define:

type MyComponentPerson = Pick<Person, "firstName" | "age">;

If you want to automatically generate this type based on the query, something like Type gql-tag in TypeScript might work for you. If that solution isn't quite right, please provide an example of your query and I may be able to help.

Matt McCutchen
  • 28,856
  • 2
  • 68
  • 75
  • Your solution certain makes sense, but I'm simply looking for a best practice and some authority on this. Let me make my post clearer. All these starter apps I've looked at only ever returns one instance of a typed `interface` without any variations. I want to see a real graphql interface with 20+ attributes and like 2 different queries that get different results and arguments on which method is the best. – Ka Mok Aug 23 '18 at 19:07
-1

Because GraphQL schema can be statically analyzed there's no need to write interfaces by hand, at all. There are many tools that does it for you.

My team's work is heavily based on GraphQL and we use GraphQL Code Generator. Instead of writing interfaces by hand and then picking from it some fields you use that tool and you get all the types and interfaces that you might need.

https://github.com/dotansimha/graphql-code-generator

It creates a type specific to your query. If you fetch only firstName and age it will create type with only that.


But there's even better way of using Apollo and generating types. Instead of wrapping a query with gql tag, then generating and attaching types to it. You can use GraphQL Code Generator in combination with library that I wrote, Apollo Angular.

The idea is to let you write only queries, in .graphql files so you get full IDE support (autocompletion, validation etc) and codegen generates a ready to use service, that is strongly typed.

An example, you write query:

query MyFeed {
  feed {
    id
    name
  }
}

Next, you run codegen and in return you get an angular service called MyFeedGQL:

import { MyFeedGQL } from './graphql';

class AppComponent {
  constructor(myFeed: MyFeedGQL) {
    this.myFeed.watch().valueChanges.subscribe(() => ...);
  }
}

You no longer have to define types in Apollo thanks to that.

Here's an article about it: https://medium.com/the-guild/apollo-angular-code-generation-7903da1f8559

Kamil Kisiela
  • 474
  • 4
  • 5