Build a TypeScript Project From Scratch Tutorial (19 exercises)

Initialize Streak Counter

In this lesson, you will write the logic to handle initializing the streak counter.


The following resources provide more information for this lesson:


Instructor: [0:00] Let's write the logic to initialize our streak-counter. First, let's cd into streak-counter and then run pnpm add -d jsdom and add type/jsdom.
[0:11] Jsdom is going to help us mark out local storage in our tests and @types have the corresponding type declaration files for jsdom so that TypeScript, the language server, knows, hey, these are the proper types for this library.

[0:27] For instance, if you go to the DefinitelyTyped/DefinitelyTyped repo, under types, this are where all of these types live, and it's a very, very long list. It's over a thousand files. It's important to know that when you're working in this ecosystem and you need to install packages, you usually do npm install addtype/package name.

[0:48] Now I want you to open index.test.ts. We're going to paste in a couple of test suites, which you'll be able to get from the repo. First, we'll need to add beforeEach to our imports, like so. We'll also need to write this function, because it doesn't exist yet.

[1:05] Just briefly looking at this, there's a couple of tests to make sure that our streak is working as expected. This one, it's return streak object with the current count, start date, and last login date. This is just making sure that our object has the right shape. Our streak should start at 1 and keep track of last login date. Then we have a helper function up here called formatted-date. Great.

[1:26] Let's open up our terminal, cd into streak-counter, and run pnpm run test. This will run vitus, and we should see a TypeScript error. We have one failing. Let's take a look. Failed to load source index. Let's fix that.

[1:41] Inside of our streak-counter, let's create a source directory, and inside of there, let's create a file called index.ts. We're going to export function streak-counter and for now, we'll just return an empty object. We'll save that, and I believe if we hit save in our test, it'll rerun. Now we'll see that our actual tests are failing.

[2:03] Let's work through these one by one. If we go into index.test.ts, I'll bring this down. Let's look at the first one. Here, we'll see streak-counter, and we're taking two arguments. It says the first thing is expect zero arguments, but got two.

[2:17] Let's talk about parameter type annotations. Functions accept parameters. The first one is going to be _localStorage, with an underscore, equal to storage. We're doing the underscore here because if we don't otherwise, we're going to be referencing the global value localStorage. Just to make sure we're not accidentally doing that, we prefix it with the underscore.

[2:39] This is a parameter type annotation. You see the colon and then space and the type. Essentially, we're adding a type annotation, AKA the type, for this value. Our second one is going to be date, and we'll call this date as is and use the type date.

[2:57] Now if we go back to index.test.ts, we no longer have those red squigglies. That's because our function, we're calling the function with the correct parameters. Now let's take a look.

[3:08] They're still failing, but that's OK. The first thing it says has own property current count as. We're essentially just checking that the returned value, which in this case is an empty object, should have three keys. Current count, start date, and last login date. Let's come back here.

[3:25] Now we're going to use another type called an interface. We're going to put streak as the name, and it's going to have three keys, which if we look back here, remember, it's current count, start date, and last login date.

[3:38] Current count is going to be of type number, last login date is going to be a string, and start date is going to be a string. We'll work with strings instead of dates just to keep things extra simple. Great.

[3:52] Now if we come back, let's see. Expected to be true. Interesting. What's happening here? We expected it to be true. We received . Ah, right, we need to use it. Let's do two things. We're going to add a colon here. This is going to be the return type annotation.

[4:10] Functions return values, so when you hover over, you'll see a function name, followed by parameters, followed by parameter type annotations. This last colon is telling us what the function returns, which is a streak. If we hover here, it says, hey, type empty object is missing these properties. Let's add them.

[4:30] We'll say current count, and it's a number, so we'll do . The start date, which is a string, which we'll just do to-do, and then last login date, also a string, which we'll leave as to-do. Now if we save, come back and look at our terminal, now we have one test passing. Awesome.

[4:45] Let's see here. What's failing? It's return the streak starting at 1 and keep track of last login date. Cool. The first thing, the current count should be 1 instead of , because when you start a new streak, it starts at 1. We'll do that and hit save, and if we come back, now the second assertion is failing. Expected to-do to be 12/5/2022. All right.

[5:07] We'll do a couple of things. We'll come here and we'll use formatted-date. That will auto-import, pass state, and we'll do the same thing here and pass in date. Now if we save, we'll see that everything is passing. Awesome.