Check out a free preview of the full TypeScript Fundamentals, v3 course:
The "Typing Functions" Lesson is part of the full, TypeScript Fundamentals, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Mike demonstrates the benefits of explicitly defining return types and discusses how to narrow down the location return type errors. A student's question regarding type and test driven development is also covered in this segment.

Get Unlimited Access Now

Transcript from the "Typing Functions" Lesson

>> So I prefer to explicitly state return types. And I'm going to show you why, it has to do with where problems are surfaced. Do you want those problems to be surfaced at the place where you declare the function? Or do you want them to be surfaced where you use the function?

[00:00:21] So my preference is this, and we can see that once we define a return type we get an additional benefit there. And that is, every code path that goes through the implementation of this function must live up to what you state will happen. Meaning, even if you had like six or seven different branches that happened based on different conditions, lots of complicated logic for adding two numbers together.

[00:00:46] Every one of those has to return a number or throw but you can't return null and one of those cases, this will give you guarantees that everything is handled down every path that that could possibly be taken. I want this error here, surfaced at the function declaration. Not at where I'm using it, so I'm gonna pop up in the TypeScript playground and we can look at the alternative here.

[00:01:20] So I can add 3 and 4 here, let's get rid of this. Yeah, this is a great example. So what's happening here is add, it has a return type void, meaning it doesn't return and rather than talk about void now, let's return null, right? Add returns null, so right now let's say I use add a bunch of different places in my program.

[00:01:53] They're all gonna light up, and the errors happening at the point of invocation. If I state my intentions up front with a return type that's explicit, Now, all of my usage is fine, because I mean, it's not gonna run the way I would want it to run. But it returns a number that's what I've stated, should happen, will happen.

[00:02:23] And now this is one thing that I need to fix, so it just reduces the noise. You're not seeing like 15 different things light up, you're seeing 1 thing light up, and it's taking you to the location of where you need to make a fix. This is better, in my opinion, that's why I like explicit return types.

[00:02:41] Let's you state your intentions upfront, make sure you follow through with them. And it surfaces problems where you need to fix the problems.
>> Mike, this seems, kinda like local preventative medicine, almost like when you were, that last thing you did, I'm sorry. When you are declaring, I guess what the output type should be?

>> Yep.
>> So that you don't leave locally in your code and you can detect the error before it happens, I suppose, just trying to, in simple terms for me,
>> Sure, let me tell you the way I think about this. So test driven development isn't for everybody, but I like type driven development, meaning, sometimes I will state what I'm trying to do and put the usage of the function I have not implemented yet in place.

[00:03:40] And I can define what I think I need in terms of inputs and outputs, and then I can implement it later. So I like to use this as a tool and frequently I'll end up doing this. Write the code that I want to be able to run and then fill in all of my functions.

[00:03:58] Now, you talk about this as local preventative medicine. I think about this as local boundaries, where instead of validating that your whole program works by running an extensive test suite that tests everything all together. You can on a per function basis, ensure that within this function, I am returning the right thing, I am accepting the right thing, and then you can move on to another function.

[00:04:29] Now, TypeScript is not a replacement for tests, it's not a replacement for unit tests. But this does give you the ability to shift between micro and macro. Is this function doing the right thing, is it returning the right thing? Do I have the right guarantees around it and then shift out, and let's test the whole program, and let's make sure that things work the way they should.

[00:04:56] And I say TypeScript is not a replacement for tests because all it does is checks types, right? It doesn't actually ensure that a and b actually gets summed up together. So if you were writing tests that specifically validated only the type information, yes, you can eliminate those. But, I think it's kind of a dangerous statement to say, You no longer have to write a lot of unit tests.

[00:05:24] TypeScript has nothing to do with behavior that's still left to JavaScript. So, hopefully we're writing those kinds of unit tests to begin with, don't stop writing this.