If you are anything like me, you’ve probably noticed that TypeScript has been getting a lot of name drops around the proverbial water-cooler these days. Maybe you’ve even thought, ‘I bet TypeScript would look great on my resume,’ but haven’t quite found the time to fully investigate what all the hoopla is about. Well, let me tell you, dear Reader, if you have a healthy understanding of JavaScript, TypeScript adds a superset of tools on top of JavaScript. Typescript and javascript are very similar. Something that helped me early on was to not only think about types but to focus on shapes. Think about TypeScript as one of the colorful children's toys in the picture above. As long as you aren’t cheating and just passing everything through the square hole like this monster, each shape has a unique passage that it can move through. You’ll run into trouble trying to get the wrong shape to fit through the wrong passageway.
In normal JavaScript, when you create variables or functions or pass props, you never have to specify what "data" shape you are expecting them to be. It’s what is both wonderful and frustratingly bug-producing about JavaScript applications. You have the freedom to create a function that adds two numbers and returns their sum, and then down the road feed your functions two strings instead of numbers and laugh maniacally as you watch all your code break. TypeScript and static typing, in that example, would enable you to declare what type or data shape you expect and send the typescript compiler gives warnings if you are attempting to smash that circle-shaped string through that triangle-shaped number opening.
Now, you might be wondering in this example--as well as those that follow--why you might need this safety net at all. All of these instances are small and simple enough that you could easily find the bug without the aid of TypeScript code. That brings up a great point, dear Reader: TypeScript was created with larger projects in mind, especially the kind where multiple people work on code over multiple sprints, and things have the potential to get real messy if there’s a tiny bug somewhere way back in the code base’s lineage. But, like many new things, it’s best to get a grasp on TypeScript in small bite-size examples and to incorporate it into small projects first so when you get to work on big projects you feel confident that your proper use of TypeScript types will prevent MANY annoying and hard-to-find bugs further on down the line.
Let’s get started setting some basic types. I’ve opened visual studio code, created a variable here, and set it to Harvey because he’s my current dog.
The name of my current dog might change, but I don’t want its typescript type to ever change. I want myDog to always be a string because it will always be a name. So, I can declare its type to be a string with a colon after the myDog declaration, followed by ‘string’.
Easy right? And now, for fun, let’s say somewhere down the line someone tries to make myDog a number.
TypeScript gets mad when type checking and lets me know that I can’t force a type number peg, through the type string opening. Most excellent.
Okay, let’s say this time I want to set a type to an array of dogs. Here’s my array:
We have two shapes to think about here. There’s the shape of the array, as well as the shape of the array’s contents. In this case, I know a couple of dog names, so my array is full of strings. I can set the type once again with a colon followed by ‘string’, but then state that it is an array of strings by placing empty array brackets immediately following ‘string.’
Perfect! Our type is set. For fun, let’s try and add a non-string to this array.
Again, TypeScript rejects it. We have clearly set our expectations for the shape of this array with string[], and a number cannot pass through in a string’s place.
Here’s where thinking about shape in terms of type really starts to help. I’ve got an object declared here:
Much like with an array, we have multiple shapes to think about here. You don’t always need to declare the type of the entire object, but it helps to. To define the object’s shape, you set up an interface. Interfaces are a template, naming the types within an object. In the example below I’ve created an interface for my dog object.
Notice the question mark after furLength on line 4? This means that furLength is an optional property and does not have to be present for my file to run. This option separates TypeScript from other higher languages, where type is always required and can be very useful in certain instances. We will touch more on this in a moment.
Now that we have our interface created and have effectively declared the shape of a type of object, we can declare my object Harvey to be of this shape.
Just for fun, let’s play around with the Harvey object. furLength is an optional property so notice how TypeScript is satisfied in its absence in the first image below. In the second image, I’ve commented out furColor, which is NOT an optional property, and TypeScript gets mad when type checking and throws an error. This is the behavior we want, so thanks very much TypeScript!
With TypeScript, you can control not only what goes into a function, but also what is returned from it. In the image below I have a function without set types and, as you can see, my TypeScript source code is ticked off about it.
This function takes an object and returns a single property from that object. In this example, it takes in a dog object and returns the dog’s age. Luckily since I’ve already defined the shape of my dog object, I can set the dog parameter to type newDog. I’m expecting to receive the dog’s age from this function, which is a number type, so following the function parameter parentheses, I can set the return type to number. You can see examples of this on line 13 of the image below.
I tied that last example in with the one before it, but let’s say you are writing a new function and you won’t be feeding an object to it and therefore do not require an interface to set the shape. Here’s a simple addition function.
To create the function’s shape with Typescript, we once again need to set the type of the parameters as well as the type of the return value. This basic function takes in two numbers (duh) and returns a number (duh). But setting the type will help make sure a sneaky string doesn’t somehow find its way in there down the line and ruin everything.
At this juncture, we’ve reached the end of our time together. I hope this brief introduction to TypeScript has provided you with some general concepts to begin your true journey integrating TypeScript into your projects. It may be basic to mention docs, but if you struggle with any of this, the TypeScript doc website is very easy to navigate and get answers from. If you are the type (get it?) that learns better by writing code, be sure to check out our Typescript Code Review Club. Also, I’ll be back soon with a post exploring further TypeScript concepts in the not-too-distant future.
Try another post: 5 Essential VSCode Extensions for React Developers
Kick your software into gear