Beginner's TypeScript Section 18 exercises
solution

Update Return Type Annotations for Async Functions

There are several solutions here.

Do What TypeScript Suggests

In the starting point of the code, hovering over the error message in VS Code pops up a message:


The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<LukeSkywalker

Loading solution

Transcript

0:00 There are several solutions here. The first one is this. This is the one that TypeScript hints at you to do when you add this return type. The return type of an async function or method must be the global promised T type. Did you mean to write Promise Luke Skywalker? This is really cool.

0:18 It's because we've specified this as an async function. What it means is if we were to use this, if we were to say const luke equals fetch Luke Skywalker, this attribute here is not Luke Skywalker. It's going to be a promise that represents Luke Skywalker that will resolve to be Luke Skywalker. We should wrap it in promise here.

0:44 This syntax is exactly the same as the array syntax I showed you earlier. There's no other way to represent promises here. This is what we've got. It's pretty good. We got our fetch Luke Skywalker. This is the first solution and it works. This is probably what I recommend, maybe.

1:02 Let's look at the third solution first. The third solution is a little bit funky in terms of formatting. If I remove this and I say data is this, data is typed as any. Now, any is a really interesting type in TypeScript because it doesn't give you any autocomplete when you use it. Data dot blah, blah, blah, blah, I'm not getting any of my name, height, mass, hair color stuff.

1:29 This data here, because we've awaited this fetch, I can actually say this is Luke Skywalker there using the syntax that we've seen before. Now, my data is typed as Luke Skywalker, so I'll get access to data dot birth year, data dot eye color, etc.

1:47 This is one way to do it. What this means then is if I hover over fetch Luke Skywalker, suddenly, it's inferred, because it's an async function, that we return a Promise Luke Skywalker. I can also do both if I want to. I can say Promise Luke Skywalker just here, which is pretty nice, Promise Luke Skywalker.

2:08 Now, if I return a number, let's say, then it's going to yell at me because data doesn't represent the thing. You notice here that we are lying to ourselves a little bit in all of these cases because, really, we don't know what this is going to return, or TypeScript itself doesn't know it. We're having to tell it.

2:32 The third way to do this is the most out there, or at least, you may have seen this syntax before if you've come across TypeScript, which is we're saying return data as Luke Skywalker. This syntax is a cast. What this does is it's casting data to Luke Skywalker. This could actually be anything.

2:54 I could say const matt -- This was always my dream when I was a kid -- as Luke Skywalker. Now, we can say that Matt is Luke Skywalker. If I were to change this to we need to ensure that Matt is assignable to Luke Skywalker, then we actually get errors here. Type thing is missing the following, blah, blah, blah, blah, blah, blah. It's yelling at me because I've not added all of these properties.

3:26 The as is a more powerful way, a stronger way to tell TypeScript what you think things should be. Of course, because TypeScript is really clever, then the return type of this is still going to be a Promise Luke Skywalker. We're still going to need to wait it and TypeScript is still relatively happy.

3:46 I do like that this shows you the difference between this as and this syntax, just the assigning syntax. This is a bit safer. What you should probably do in all cases is this. Sometimes you'll run up against cases where this is the better option.

4:06 Here, because data is any, any is a type that's assignable to anything. It's like TypeScript has no idea what it could be, and it literally doesn't. Unless it literally goes and fetches this data, it has no idea what that data shape is going to be. That's not TypeScript's business. It's not going to do that for you. We need to tell it. We can either do it with this syntax or with this syntax here.