This course has been updated! We now recommend you take the TypeScript Fundamentals, v3 course.
Transcript from the "Definite Assignment & Lazy Initialization" Lesson
[00:00:00]
>> Mike North: In this situation, w're just providing an initializer by kind of another means. We could just as easily moved this up as a property initializer. But I'm pointing out that we can do in either place. Additionally, if my TypeScript settings are correct here and they are. You'll note that we're getting yelled at here, ignore this first message.
[00:00:29] We just see that a lot, cuz we have a lot of classes and things that are never read, cuz it's just a page of examples. This error message is interesting, password has no initializer and it's not definitely assigned in the constructor. So what we're seeing here is we've stated that password is a string.
[00:00:49] And for any downstream code, any methods, they might be able to access private field. If they try to access password they expect to get a string back, and currently that's not going to happen. Even if we had a condition here where if we said like if (phone > 0).
[00:01:14]
>> Mike North: Initialize this, we'll still get an error because analyzing the various paths, we can take though our contractor. One or more have been identified where we would not end up setting passwords up with the value. There are couple ways we can handle this. One way would be to decide that this is the problem, we just should always initiatialize password.
[00:01:37] The other way would be to add the possibility that this is undefined. And now anyone who attempts to access password, they'll get string or undefined. They'll have to use one of those guards that we showed an example of before. If (this.password), and then within that block password will be a string.
[00:02:01] So that's one thing we could do. Here's another thing we could do. We could use a new operator here and this is one we'd wanna use if we really know that phone number like it's guaranteed to be greater than zero. Basically you know for a fact that you're always gonna go down this branch and it's gonna be okay.
[00:02:24] Or maybe every time you instantiate this class, you call a method on it to do some asynchronous setup, right? Like if we did this.
>> Mike North: An asynchronous init function, there's no way to make a constructor asynchronous. Sorry, I keep saving in things auto-format. There's no way to make something asynchronous, but perhaps we just know that wherever we use this, right after we construct it we call init and then everything downstream should be able to depend on password being there.
[00:02:58] In this case, we would use something called the definite assignment operator and it is an exclamation mark. What this is saying is trust me TypeScript, I'm taking responsibility for making sure that this field gets initialized properly. So this is an area where I want you to let me handle this and don't cause an error at this point in the code.
[00:03:27] So, where my another useful place for this kind of thing be? Raise your hand if you've used Angular, React, Ember, Polymer, or Vue? Awesome, so, do you find that you end up directly instantiating components? You have a component class, do you find you are ever calling new component, and then rendering it and putting that element in the DOM, or is the framework handling it for you?
[00:03:59] Framework handles it for you. So there are often life cycle hooks where you might be setting things up, setting up properties. And in an early life cycle hook, you might take care of putting password in place. And you just know that this is the first thing that is gonna be called, the frameworks doing the constructor stuff.
[00:04:20] I'll take responsibility, I know there's this little gap, very early in the life cycle, where password's not there, but realistically, I'm not doing anything with that code. And that simplifies downstream stuff, where you can just access password, and trust that it will be there. Here's another related tip.
[00:04:40] Let's say that realistically we don't know if passwords are gonna necessarily be there, maybe in the middle of its life cycle. Your component might get something, right? And you still wanna simplify things a bit. I would do something like this.
>> Mike North: I would have a value that has the potential to be undefined,
[00:05:08]
>> Mike North: And I could do private get password. This is just a ECMAScript 5 getter, ES5 getter, it's worked for a long time. It works natively in IE11 and 10.
>> Mike North: If the password value doesn't exist, we'll create it lazily,
>> Mike North: And then return it.
>> Mike North: And we can say this is definitely a string.
[00:05:46] The end result is, here, we have a property that's a string and we can access password wherever we need it, it's lazily created. The first time we ask for it and then it's cached on the instance. And so we could repeatedly go ahead and keep asking for it, we still instantiate it once.
[00:06:06] But this is another trick for things that may start out as undefined and you can kind of create a lazily instantiated value like this.
>> Mike North: Questions? Cool, this should be mostly regular JavaScript stuff, especially that. It's kind of underutilized but getters have been around for a while.