Transcript from the "Interfaces" Lesson
>> Scott Moss: Cool so we're gonna move on to unions and interfaces which I think are like, they either make or break you. Honestly I love interfaces and unions but then I hate interfaces and unions, like. Because you've got to do so much to get around them as you'll find out.
[00:00:18] So let's talk about those. Let's just talk about what the solve. I'm gonna walk through each one of them and then we'll talk about the slight difference between the two, okay. So, unions and interfaces, basically what they're trying to solve is where you might have the possibility of having a group of different return types for a value.
[00:00:43] So for Instance, let's say we wanted to, okay, like for favefood, it could be either a burger, a nacho or a taco, right? But what if wanted it to be either, some other type here and not just a string. What if we had another type called Food, right?
[00:01:05] And this Food had a name on it, and it was a String, right? And instead of returning that, we actually wanted to return a different type. We couldn't do this with enums, cuz enums only return strings, they don't return custom types. So interfaces in unions allow us to group types together so they can represent a selection of one type for our return value.
[00:01:32] So let's use this in practice coz it sounds super confusing, but it's much easier in practice. So let's do this. So we'll make a I'm sick of person. Let's just do animal. So we'll say, we'll make a Animal type here. And then let's say the Animal is a type.
[00:01:51] And it could be a, let's do a enum here. Let's get complicated. AnimalType. And it can be a dog or a cat. Okay, so we'll put AnimalType here.
>> Scott Moss: And then what's the one thing that a cat can do that a dog can't do or what's the trait of a cat that a dog doesn't have?
>> Speaker 2: Meow versus bark.
>> Scott Moss: Meow versus bark? [INAUDIBLE] Well, those are both sounds, but what's an actual different trait.
>> Speaker 3: Fall from very high places?
>> Speaker 4: [LAUGH].
>> Speaker 5: Nine lives versus one. [INAUDIBLE] [LAUGH]
>> Scott Moss: Alright. All right, okay. All right, so we'll say lives. So for cats, cats have lives and we'll put Int here.
[00:02:45] And then something for a dog, let's just say
>> Speaker 2: Personality.
>> Scott Moss: Yeah. Personality type. [LAUGH] Yeah, there we go. So let's just say that only dogs have personalities and only cats have lives. Cool. So we can do that. And then what we'd have to do here is, if we were to write a query for this.
[00:03:07] We'd have to determine on the front end which animal we were talking about. Right? So we'd have to, once we get our query, we'd have to look at the type to see if this is a cat or a dog. We'd have to look to see if lives was there.
[00:03:20] Or we'd have to look at personality to see, we'd have to infer somehow. That this in deed was a cat or a dog somehow. But what if GraphQL can do that for us? So that's what we're gonna do interfaces in unions. So what we're gonna do is we're actually gonna turn this into a interface like this.
[00:03:37] So now animals is no longer a type, it's an interface. Same thing you would, an interface in GraphQL is the same thing that's the interface in type script or java, any type language is basically the same thing. I want an interface called animal, then I'm going to make two types called Dog that implements the animal interface.
[00:04:04] And I will make another one called Cat that will also activate the animal interface. And they both share at least one common thing and that is a type. So I am going to put that there. They both have a type property. And, but only cats have lives so I am going to put that on cat and only dos have personalities so I'm gonna put that on dog and then im gonna remove the two from the interface like that.
[00:04:33] So now this is saying dog implements animal. Cat implements animal. They both have type. Because that's what they share from animal, but distinctively a dog has a personality of some value and a cat has lives of some value. Now the rule of interface is that whatever the interface describes, whatever fields it describes you must also declare them on the types that implement them.
[00:04:57] So if I had four other filter, I must also put those fields here and I must also put those fields here. They have to be the same exact thing. So you still have to copy and past them down, but then from there you can put whatever you want distinctively for that type.
>> Speaker 6: What's the advantage of having an interface if you have to put it in the type anyways?
>> Scott Moss: Yeah, so the interface is not so much for like decreasing repetition in the schema it's more about decreasing repetition in the query. So yeah, you might be thinking like, I just had to copy and paste it anyway.
[00:05:29] Yeah, you still gotta do it here. They don't, it's not for optimizing this, it's literally only optimizing for the query. So when you get to the query you'll see where the benefit comes, yeah. It's definitely a query thing, not so much a server thing.
>> Speaker 7: I had a question.
>> Scott Moss: Yes?
>> Speaker 7: If a field is required on the interface, also require on implementing and you make it not require on the implementation.
>> Scott Moss: You literally have to copy everything that's in it's interface and put it here or it'll break. Like anyone compile either like nope, this is not right.
[00:05:59] It don't even work right. So yeah, whatever the interface is, you have to pu it here. I wish they could get to the point where we don't have to copy like you said because it's kind of annoying But then again I see why they do it because they want it be strongly typed.
[00:06:11] And they want you to be aware and they don't want to make inferences. But that's the reality of what's happening now. So, let's try to resolve this because the other thing is, like, we have an interface and we have a cat and a dog. How does Graphql know which type is what?
[00:06:30] Right? So let me bring that up. So let's say I write a query for an animal. I want to get an animal right. And it doesn't take, it doesn't really, actually let's just take. Actually it's not going to take anything. And it's just going to return animal interface.
[00:06:47] How does that work? How can you return an interface?
>> Scott Moss: All right, like how does that even work? Like you can only return types. Exactly. So we have to tell GraphQLhow to resolve the animal interface to eventually be a dog or a cat. So be right a special resolver for this.
[00:07:05] So where are we gonna do that? Let's just put this on the side. We'll come to the resolvers and the first thing is we need to make a property for the animal interface here. So that's the first thing we're gonna do. We're gonna say, all right, cool. For animal, we're gonna make this property here and then this is where we need to tell GraphQL how to, given an animal, how to know if it's a cat or a dog?
[00:07:29] So we could ask for its specific fields. So given an animal, we can use a special method as a resolver, which is __resolveType. So this __resolveType, this is something, this is a convention mostly in Apollo based GraphQL servers. I've seen other servers just do resolve type, without the underscore underscore.
[00:07:53] So really depends on the server you're using, but if you're writing a Graphql server in Node, you're probably using some Apollo based ones, if you're not, you should. And the way it resolves is the __resolveType, which is a method. That you can use. And as the first argument it's going to get the object of this animal.
[00:08:14] So we're gonna have an animal here. So we're gonna get an animal. And we'll resolve the animal in a minute. Unlike the other resolvers where the second argument is the args that's passed in This one doesn't have any args, cuz it's an interface. So actually, the second argument's just gonna be context.
[00:08:32] And then, the third argument's gonna be info. So __resolvetType only has three arguments. There's no args as a second argument here, so it's only three. But you, most likely, won't even need those, at least in our case. So, how do we determine if an animal is a cat or dog any body know just by looking at this types, what can we look at to know this is a dog or cat?
>> Speaker 2: Personality
>> Scott Moss: Which one?
>> Speaker 2: Personality and lives.
>> Scott Moss: Personality and live we can identify further what's one that for sure gonna tell us what right?
>> Speaker 8: Type.
>> Scott Moss: Yeah. We gonna look at type, the type already say Dog or Cat. Right? So that's what we'll do. We'll say, you know what that's just too much work.
[00:09:19] I thought about it and then I decided not to. Lets do the if statement. So if animal dot type === 'cat'. And all we have to do, the return value that we have to out here Is the name of the type in GraphQL that we want this interface to resolve to.
[00:09:39] So in this case if it's a Cat, we want to return cat with a capital T because that's the name of this type here. So this is telling GraphQL, hey, when we get an animal and it has a type property who is equal cat. And we know there is a lowercase cat because we made a interface with a lowercase cat.
[00:09:58] Then I want you to return or resolve to the Cat type which is this uppercase Cat right here. And then because we only have on one other option I am just going to put else ,return Dog
>> Scott Moss: And then now, when we get an animal it will know which one are results.
[00:10:19] So let's walk through this whole single thing and we'll put it all together. So the first thing we need to do is let's make a resolver for this query which is called animal. So that's the first thing we need to do. So we need to go up here and we'll make an animal resolver and let's just hard code a cap for now.
[00:10:41] So we'll just return a hybrid animal that's both cat and dog. So it doesn't matter, so we'll just do that. So we'll return it has a type and I'm just gonna put cat for now but it's gonna be both Lives, we'll just put nine and then also personality, just so we can see.
[00:10:59] Personality is attack dog. Alright, so we got this object it's a cat but it's also got a personality of what's going on here. So then we have this resolve type, so like we're good to go. So next thing we need to do is, let's see we got this already.
[00:11:20] Cool, we can actually just restart the server and run this. And see what it looks like. Open a new tab here and I just wanna get an animal
>> Scott Moss: There we go. And then what I want to do is, I want to be able to get the lives of an animal, but as you see, as I'm typing, lives doesn't come up.
[00:11:48] It's not giving me the autocomplete. The only thing it's giving me is type. Ignore this typename thing, that's like GraphQL specific, but it's giving me type. That's a thing that I made. Why is it not letting me look at lives or personality?
>> Speaker 2: Because you're only asking it for an interface.
>> Scott Moss: Right, I'm only asking it for an interface. And the only thing that exists on the animal interface is type. That's it, that's the common field. So I can ask for type. So if I ask for this I'll get back cat, cool, okay. but now I want to get the lives of that cat so do I do that?
[00:12:21] Can't do that. So how do I get the lives? Anybody want to take a shot? Fragment, yeah. We just talked about it, it's fragments. So I would actually use a fragment syntax on the cap type to get the lives. Which give you lives, so basically what this is saying is that cool give me the common fields on animal which in this case is the only type but if the return type is cap give me the lives.
[00:12:54] I can also say, if the returned type is Dog, give me the personality. But you notice, I'm not getting a personality here, even though we put a personality here, why is that?
>> Speaker 2: Because personality's not on dog or not on cat, sorry.
>> Scott Moss: Right and how does GraphQL know that this is a cat?
>> Speaker 2: The type, yeah.
>> Scott Moss: It's this check right here, exactly. So if we put some logs in here, we can see. I am a cat.
>> Scott Moss: So let's try that.
>> Scott Moss: My God, come on. So let's run this, look at the logs and you can see I am a cat.
[00:13:44] That's because animal dot type was cat. And just to clarify, if I go back up and change this to dog this is now going to be a dog and we won't see lives anymore, we'll see personality. There we go.
>> Scott Moss: Even though the object itself return all the properties on it, I was not able to access them because I split it up into an interface with multiple types.
>> Scott Moss: And that's basically what interface is. So it's a couple steps just to go through it one more time. You have an interface that describes common fields and then you have types that implement those common fields and then add distinctive fields for those types, that's step one. Step two is you need to make a resolve type method on the interface resolver to tell GraphQL what type to resolve to.
[00:14:53] So that's step two. And then step three, is this you just need to resolve the top level query which in this case, for us, was just the animal query. That takes no arguments.