Use 'as const' to Infer a Tuple return type
Hovering over our variables inside of useId
is going to tell us what's going wrong.
Inside of useId
, when hovering over id
in the return statement we can see a const id: string
, and hovering over setId
shows React.Dispatch
with a string:
// inside of useIdreturn [id, se
Transcript
00:00 So, let's take a look and actually hover over UseID, because this is what's going to tell us what's going wrong. You can see that actually, when we return the things from UseID, it gets inferred as a string here, and this kind of React.dispatch.setStackAction thing with a string in there.
00:16 And that's all good, that's fine, but if we hover over this, you can see that it actually unions those and puts them inside an array here. So this is now an array of those possible things. So that means when we come down to here, both of these have the same type.
00:33 This SetID is a string or the dispatch, and this one is an ID, string or dispatch. So the key here is to make TypeScript understand that the thing we're returning from this is not going to change, it's not going to be appended to, right? Because if you think about this, we've just basically got an array here, right?
00:51 So if I just add R here, and technically, I could push things to this. So I could push a new string to this, right? So we need to tell TypeScript that this is a tuple, not an array. The way we can do this, there's two different ways. We can either say, okay, let's strongly type this inside here.
01:10 And so this one is a React.dispatch, React.setStateFunction or ActionString, and we can stick that in there and that will work. The reason that works is because it explicitly tells TypeScript what this returns, and now if we forget to leave, like if we just leave one off, then it's going to yell at us because the target requires two elements.
01:29 And if we add another one to this, like this, then it's going to yell at us again. There is a really nice different way to do this though, which is you can use asConst on the returned array. This is super nice because what this does is it basically tells TypeScript to infer that this is a tuple and not a big array.
01:48 So you can see here that if we remove the asConst, we get that kind of strange union type that we were dealing with before just there. But then if we put this on here, suddenly it takes a read-only thing, which is useful in itself, and we've got a tuple,
02:04 the first element containing a string and the second element containing React.dispatch. This I think is my preferred solution. It's just beautiful.