Split Functions Into Two Different Call Signatures
As a reminder, here's what the original function signature for useData
looked like:
function useData<T>(params: { fetchData: () => Promise<T>; initialData?: T }): {
getData: () => T | undefined;
} {
...
To solve this challenge, we'll remove the optional part of the original
Transcript
0:00 When we call use data, we're now splitting it into two different call signatures. That's a way to think about function overloads. There's the call signature without initial data and there's the call signature with initial data.
0:15 Those two things return different return types, because what you can see here then is, in this call signature, this is going to return T or undefined. In the other one, it's going to return T. In here, then, this is going to work now. I've just patched it. Of course, we've got an error here because T is T or undefined inside here.
0:39 What we need to do is split this out into two different call signatures, two different function overloads. I'm going to copy this and just paste it twice. That's going to give us two identical function overloads, which is the same as just having this implementation signature down here.
0:55 One of them is going to have no initial data. That no initial data is going to return T or undefined here. This one, it's going to have initial data. It's not going to be optional either. You've got to pass it. We're splitting out the optional parts into two different call signatures. On this one, it's going to be T just here.
1:16 Now everything works. Because we're using a pretty loose type signature inside here, we've got the optional property inside there, we've got T or undefined here, then it all just fits together really nicely. Now getData always returns a number.
1:34 This functionality is really cool if you're building things which feel like they have an optional property but are, in fact, two different call signatures. That's something to really wrap your head around with function overloads, that really they split your function up into different ways of calling it.
1:52 In this case, function overloads are perfect because we have different type signatures coming out at the end. If they were the same type signature, then maybe it wouldn't make sense to split them up into function overloads, but because they have two different ones, then it doesn't make sense and it works really nicely.