Learning TypeScript Data Types - From Zero to Hero
Jonathan Sexton
Posted on October 28, 2019
It's all the rage these days in the world of web development - TypeScript. I'd wager by now you have heard about it, even in passing. But, if you haven't or if you're just curious then you've come to the right place my friend!
I'm currently learning TypeScript in conjunction with Angular (an article on this is in the works, so stay tuned!) because it's what our web application is built in at work. I decided to write up something easy and simple to follow so you can get up and running with TypeScript data types.
I'll break this article up into two posts for simplicity - the first will be a brief overview of what TypeScript is, the data types, and some supporting examples. The second article will be focused on getting TypeScript installed and running locally on your machine.
What Is It?
Before we start, here's a super condensed description of TypeScript in my own words. It's a superset of JavaScript - which essentially means it's a form of JavaScript that gives you certain benefits along with all of the greatness included in 'vanilla' JavaScript. It's an open source language written and maintained by Microsoft.
TypeScript transpiles to JavaScript and will run in any environment that native JavaScript runs. You may use TypeScript for both front end and back end applications.
It's written just like JavaScript, with a few exceptions that we'll go over soon. Here's an example of some TypeScript:
Try not to focus on all of the colons and extra stuff you see above, we'll dig into that below. Instead, focus on the things that stand out - we're just declaring variables with values, these are strings, arrays, and objects just like in JavaScript.
Another great thing that I've learned about TypeScript is you can mix JavaScript in with the code and have no issues doing so. Check the screenshot below (this is inside an Angular app):
Data Types
Let's get started with the fun stuff - data types! (There are a few data types we won't cover - never, null, undefined. This is simply because there isn't much to them. I want you to know they exist and if you'd like to dig in more on those types, here is a link to the official TypeScript documentation for your reference.)
TypeScript will infer the type of data assigned to a variable without you explicitly setting the type but for simplicity and good measure I like to declare the data type when declaring my variables.
We assign data types by simply placing a colon after the variable name but before the equal sign:
const {variable name}: {variable type} = {variable value}
This is the convention that the majority of TypeScript data types are declared with the exception of functions and objects.
Some data types come with a bit more complexity than that, but you get the general idea. Below are some brief explanations of data types and examples of how to declare them.
Boolean
Booleans in TypeScript work the same way as they do in JavaScript. Variables of data type boolean are declared like so:
const myBool: boolean = false
;
String
Strings in TypeScript work the same way as they do in JavaScript. Variables of data type string are declared like so:
let myString: string = 'bacon'
Number
Numbers in TypeScript work the same way as they do in JavaScript. Variables of data type number are declared like so:
const myNum: number = 1207;
Array
Arrays in TypeScript are, like other data types, just like arrays in JavaScript. Variables of data type array are declared two separate ways :
const myArr: number[] = [12, 90, 71];
The above way is how you'd declare an array if all of the elements inside that array are numbers.
const myArr: Array<number> = [12, 90, 71];
This way of declaring an array uses the generic array type set to number. Functionally, there is no difference in how these ways produce the end result of declaring a variable with array type.
If the data types inside the array are unknown or a mixture of data types, the array can be declared using the <any> type (this is a type all on it's own that is discussed below):
const myArr: Array<any> = [12, 'thirteen', false];
This way will allow you to mix data types in the array.
Tuples
Tuples are a data type unique to TypeScript. Think of them as arrays with a fixed number of elements. This data type is best used when you know exactly how many variables you should have. It is possible to reassign the value of the indices but not the amount of elements in the tuple.
Variables of data type tuple are declared just like an array:
let mine: [number, string];
If we'd like to change the values of elements, we can do that as long as they match the types we provided when declaring our variable:
mine[0] = 14
✔️
mine[0] = 'Steve'
❌
Since we defined mine
as a tuple, the order of the values matter as well and cannot be changed Also, assigning an index outside of the original defined number will produce an error:
mine[0] = ['Dave', 71]
❌
mine = [121, 'Dave', 'Steve'];
❌
mine = [121, 'bacon'];
✔️
Function
Functions can be as explicit as you want them to be. What I mean by that is we can apply types to the parameters and returned values. Below are two examples:
This function will throw an error if any value is returned that is not a number or points to a number. It may return a variable only if that variable points to a number.
Above, we're type checking on the parameters being passed into our function. This is a great way to avoid mistakes because if the number of parameters is off or if their data type doesn't match what we're expecting TypeScript will let us know with an error.
If I want a function that should not return a value, I can set the type as void (a data type that means the absence of any data. While it can be used when declaring variables it typically isn't because then we'd have to set the variable to null or undefined, I've only used when functions should have no return value) and if the function returns anything TypeScript will throw an error:
By setting the type to void I'm being explicit about my returns and establishing that while this function may still run, it should not return a value. If it does return a value, I'll get an error.
Enum
Enums are a welcomed (in my humble opinion) addition to the data types. Think of them as a more user friendly approach to giving names to numeric values. Here is an example of an enum:
enum Foods {'bacon', 'tomato', 'lettuce'};
console.log(Foods[0]) // yields 'bacon' console.log(Foods.bacon) // yields 0 console.log(Foods['lettuce']) // yields 2
It's also possible to assign the numbering index format with enums as well. Many languages including C# have enums and I'm happy to see them come to JavaScript.
You can be as creative as you want with the names. You can even change the numeric representation of the indices. If you want your first index to start at 18 instead of 0, it's as simple as:
enum Foods {'bacon'= 18, 'tomato', 'lettuce'};
console.log(Foods['bacon']); // 18
Let's say we had the value 18 but were unsure of what it mapped to in our Foods
enum, we can check that as well:
console.log(Foods[18]); // 'bacon'
One piece of noteworthy information is now that we've set the first index to start at 18, the next index will be 19, and so on following the numbering convention you establish.
Object
Objects in TypeScript are defined in similar ways as objects in JavaScript are defined. We can be as implicit or explicit with our definition as we like or as the situation dictates:
let data: = {name: 'Jonathan', age: 30, hobbies: ['running','swimming','coding']};
✔️
let data: {name: string, age: number, hobbies: string[]} = {name: 'Jonathan', age: 30, hobbies: ['running','swimming','coding']};
✔️
When creating objects, the property names are immutable, but the order in which they appear does not matter, even if we define them in a specific order.
Also, we can have simple objects like those above, or we can define complex objects that take advantage of multiple data types like the one below (this object is for demonstration purposes only):
Type Alias/Interface
With the example of a complex object above, you might be thinking this is awesome but what happens the next time I need to create a complex object? I need to type all of this out manually again?
Fear not, the type alias and interface types are here to help! A type alias is a data type that allows us to save other data types inside of it and then reference a variable instead of rewriting code over and over.
As a side note, type aliases and interfaces work in very similar ways. Both allow us to scaffold an object/blueprint for how our data should be structured. However, there are subtle differences that we won't cover here. Instead, here is a post that explains those differences in an extremely efficient fashion if you'd like to dig deeper.
There are details between the two that we should be aware of - when using the type alias, we use an equals sign (=) to declare values, the interface does not require an equal sign.
Now that we have our alias declared, it's time to make use of that alias. When we want to "build" our new variable from this alias, we simply set it as the data type:
It's important to note that the interface is specific to TypeScript. It is used only at compile time to do type checking and to catch any errors that may have slipped past our watchful eye. The data from our interface will end up in our final code, but the interface itself is compiled out.
Classes
Classes are, in part, the veritable "bread and butter" of TypeScript (at least in my humble opinion). Staying with this idea of scaffolding new objects, classes allow us to build data in a much easier way than just manually typing them out each time the need arises.
Classes can be thought of as blueprints for how our data should be defined and what actions, if any, it should be capable of through methods.
Below is an example of a class in TypeScript (which is made possible by the introduction of classes in ES6):
Now, you might be asking yourself what are the differences between a class, a type alias, and an interface? Great question! The main difference between is that classes can be instantiated (we can create new instances of them) but an interface cannot.
There are, of course, other differences but that's not contained in the scope of this article. If you'd like to dig deeper, here is a great article I read to help me understand those differences. You'll find use cases for all of them, as I have, when using TypeScript.
Union
This is, far and away, my favorite data type of TypeScript! The union type allows us declare a variable and then set it to an "either or" value. What I mean by that is let's say we're expecting data to be passed into a function but we aren't sure if it's a string or a number - this is the perfect (and intended) purpose of the union type.
We use the single pipe character (on Windows it's Shift + the key right above Enter) when defining the type. Here's what it would look like when defining a variable with union data type:
const numOfDoors: string | string[ ];
This tells TypeScript that numOfDoors is a variable that can hold either a string or an array of strings.
Here is an example of that function I mentioned earlier using union type:
Any
Any is the type we set whenever we're unsure of the types of data we'll be getting. Maybe we're getting something from a third party or some dynamic data and we aren't 100% sure if we're getting a string, a number, or maybe an array of information. This is the perfect use case for type any.
I will caution against using type any unless you absolutely must because when used we're opting out of one of the core features of TypeScript - type checking.
However, this data type has it's use cases just like all of the data types mentioned.
That's A Wrap!
I told you this wouldn't take too long :D
I hope you enjoyed this article about TypeScript and are exited about the how it can prove useful to your code base. In the next article, we'll dig into the practical side of TypeScript. We'll go over installing it, compiling, and using it in your project (not just Angular projects either)!
This was originally posted to my blog :)
While you’re here don't forget to sign up for my Newsletter – you can do that at the top right of the page when clicking the link above. I promise I’ll never spam your inbox and your information will not be shared with anyone/site. I like to occasionally send out interesting resources I find, articles about web development, and a list of my newest posts.
If you haven't yet, you can also connect with me on social media! All of my links are also at the top right of the aforementioned page. I love connecting with others and meeting new people so don't afraid to say hi :)
Have an awesome day friend and happy coding!
Posted on October 28, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.