TypeScriptGamified v1.0.1 Sample
TypeScriptGamified v1.0.1 Sample
Paula Santamaría
TypeScript Gamified
Copyright © 2023 Paula Santamaría
v1.0.1
TypeScript Gamified
Table of Contents
TypeScript Gamified
3. Class Inheritance 139
4. Access Modifiers 149
5. Implementing Interfaces 153
6. Abstract Classes 163
Challenge: Create a Dungeon Crawler REST API 172
Level 6 197
1. Type Assertions 197
2. Intersection Types 204
3. Type Guards 216
4. Type Predicates 222
5. Enums 227
Challenge: Create a Multi-platform Game 234
Thank You for Reading 270
About the Author 271
Acknowledgments 272
TypeScript Gamified
Welcome to TypeScript Gamified!
When we write code, we are usually creating an abstraction of something from the
real world. Our code describes the entities and behaviors required to achieve a
specific task. For example, an e-commerce site contains products, a checkout process,
and everything else a buyer needs to make a purchase. A messaging app includes
messages and the logic they need to go from one user to another, and so on.
Tutorials and programming books also use abstractions from the real world to create
scenarios and code samples that we can relate to, hoping that it will make it easier for
us to understand the topic.
This book uses the same strategy, but instead of drawing inspiration from the
corporate world (e.g. “Companies”, “Tasks”, and “Employees”) or using generic
examples (e.g. “Foo” and “Bar”), we will use video games for inspiration. So, we will
work with concepts like “Player”, “Weapon”, “Quest”, and “Dungeon”.
TypeScript Gamified | 6
“Writing computer software is one of the purest creative activities in the history
of human race. Programmers aren’t bound by practical limitations such as the
laws of physics; we can create exciting virtual worlds with behaviors that could
never exist in the real world.”
John Ousterhout - A Philosophy of Software Design (2018)
I aim to bring together two things I love: programming and games. To make things
more interesting for you, I have decided that the whole book will work like a game:
Content
We will go from the very basics of TypeScript to some its most complex and
commonly used features, exploring how to take advantage of its unique elements.
Note: This is not a book about game development! This book is about TypeScript.
We use games merely as an inspiration for our code examples and gamification to
make the learning experience more entertaining.
Pre-requisites
To make the most of this book, you should be familiar with the basics of JavaScript
and Object-Oriented Programming.
Knowing the very basics of node.js, like how to initialize a project (e.g., npm init ) and
how to install packages (e.g., npm install ), would also help!
TypeScript Gamified | 7
Let’s get started!
TypeScript Gamified | 8
Level 1
1. Introduction to TypeScript
What is TypeScript
TypeScript is often described as a superset of JavaScript. But what exactly does that
mean?
According to math, a superset is a set that contains all the elements of another set.
Let’s see an example:
A = {1, 2, 3}
B = {1, 2, 3, 4, 5} // --> B is a superset of A
TypeScript Gamified | 10
This also means that any valid JavaScript code is also valid TypeScript code.
So, what are these additional features? TypeScript adds a complete type system with
type checking and optional static typing, which means we can add types to our code
if we want to.
Type checking is a process that determines whether there are errors in the code
based on the types involved. This helps guarantee the type-safety of the code and
prevent bugs.
With JS, it would be up to us to figure out the mistake. TypeScript, on the other hand,
wouldn’t allow us to assign a number to a string variable in the first place.
TypeScript Gamified | 11
const mario = {
coins: 10,
points: 250,
status: 'FieryMario'
}
console.log(mario.getPoints())
If we use JavaScript, the previous code will only fail when it’s executed (possibly in
our user’s face).
However, the same code will throw the following error on TypeScript during
compilation:
Property 'getPoints' does not exist on type '{ coins: number; points: number;
status: string; }.'
TypeScript identifies our mario object as a type, and the static type checking is doing
its job by alerting us that we are misusing the type. If you use VSCode (or an IDE with
TypeScript support), you will be immediately informed of the issue and could use
IntelliSense to help you fix it.
We’ll see more about compile-time vs. runtime in Section 2 of this Level.
TypeScript Gamified | 12
Why choose TypeScript?
JavaScript has been around since 1995, while TypeScript first appeared in 2012, and
TypeScript 1.0 was released in 2014. People have been (and still are) coding in vanilla
JavaScript for years. So, why do we need static typing?
Vanilla JavaScript can handle a lot of complexity and is used on an enormous amount
of applications. It does the job. The existence of TypeScript does not mean you
should migrate all your JS projects to TypeScript or only use TypeScirpt from now on.
Sometimes vanilla JS is enough. However, to decide which is best for each project,
you should be aware of their main differences:
Type errors: Static type checking lets us know of any type errors earlier
Compiler: Required to transpile the code so the browser can interpret it
Dependencies: You’ll need extra packages to include Type definitions from
other libraries or frameworks
IntelliSense: The type definitions provide better IntelliSense
You’ll find that TypeScript characteristics usually make it a good choice when working
on larger projects and with a team. When different people work on different modules,
Types can function as a contract, helping us communicate.
TypeScript Gamified | 13
Devina is known for her TypeScript skills and pink cap. She’s working with you on a
terminal-based game.
The next feature you have to work on involves Healing Potions: The player needs to
be able to use potions to restore their HP. Devina writes the following code:
type HpPotion = {
name: string,
healingPoints: number
};
Now you need to write a usePotion function that receives the potion as a parameter.
Let’s see how it would look:
TypeScript Gamified | 14
let playerHp = 80;
usePotion({
name: 'Potion of Minor healing',
healingPoints: 10
});
// Output:
// You used: Potion of Minor healing - Healing: 10 points
// Player HP: 90.
Thanks to Devina’s HpPotion type, we know precisely what our potion object looks
like since we can count on IntelliSense to figure out its properties and use them. We
don’t even need to read her code or any further documents.
This example may look trivial, but imagine a large codebase with hundreds of types
and many other devs working on it. You can’t possibly memorize every type, and
navigating to their definition to see how they look every time wouldn’t be very
efficient.
TypeScript Gamified | 15
Most popular libraries include type definitions to facilitate our job integrating them
into our projects. They are often an essential part of the library/package
documentation!
I don’t know about you, but I don’t remember every single line of code I wrote in the
past weeks. So types help me work with code I wrote myself a week, a month, or even
years ago.
TypeScript Gamified | 16
Desktop apps with Electron
Mobile apps with React Native
Games with Phaser
and more
These are just some examples of types of applications and tools you can use. I
encourage you to do your research and find the tools that best suit your needs.
There are tons, and many are open source!
TypeScript Gamified | 17
2. TypeScript Compiler
The TypeScript compiler
The TypeScript compiler ( tsc ) is a CLI tool that transpiles our TypeScript code to
JavaScript.
Basic usage
1. Install it globally
Example
Let’s see how the compiler works. First, we’ll write a simple TypeScript class like this:
TypeScript Gamified | 18
// Knight.ts
class Knight {
public hp = 100;
Now, let’s compile the code using the following command: tsc Knight.ts .
And after running the compiler, you’ll notice a new file called Knight.js has
appeared in your project. The file should look something like this:
// Knight.js
"use strict";
class Knight {
constructor() {
this.hp = 100;
}
takeDamage(damage) {
this.hp = this.hp - damage;
}
}
Notice how Knight.js contains pure JavaScript syntax. That’s our transpiled code!
TypeScript Gamified | 19
// Knight.ts
class Knight {
public hp: number;
constructor() {
this.hp = 100;
}
public takeDamage(damage: number) : void {
this.health = this.health - damage; // Let's replace `hp` with
`health` here
}
}
And that’s how TypeScript can help us prevent errors from sneaking into our
compiled code.
TypeScript Gamified | 20
Compile-time vs. Runtime
Compile-time is the time during which the program is compiled. On the other hand,
“runtime” is when our compiled program is running. So, why is this important?
TypeScript Gamified | 21
// App.ts
We clearly specified the level should be a number , and then we set the variable with a
string ? Those are some questionable choices we are making there, I know, but bear
with me.
Our IDE will likely inform us about the issue with a nice red underline and error
message. But we are not done yet. We now open our terminal and run the compiler:
8 level = '10';
~~~~~
Found 1 error.
But if we look closely, something else happened. We now have a new App.js file in
our project. What? The compiler threw an error but transpiled the code anyway? Yes.
That’s exactly what happened.
By default, TypeScript will emit the transpiled code even if there’s an error. That may
seem odd, but it’s in balance with one of TypeScript’s core values: “Most of the time,
you know best”. Type-checking is useful but can get in the way, and TypeScript
doesn’t want to stop you from running code with type errors if you think it’s ok.
TypeScript Gamified | 22
If you want to change this behavior, tsc has a flag that does just that: --
noEmitOnError . Using this will prevent the compiler from emitting JS when there’s an
error:
These options and flags allow you to make the compiler more strict, set the target JS
version, set the output directory, etc.
But most of the time, you will probably want to use a tsconfig.json file instead.
To compile a project, we’ll usually need a tsconfig.json file. This file serves two
TypeScript Gamified | 23
primary purposes: 1. The directory where this file is located is considered the root
directory of the project by the compiler. 2. It contains the compiler options
When we invoke tsc , the compiler searches for the tsconfig.json file and compiles
the project from the root directory, using the configuration options we specified in
the file.
{
"compilerOptions": {
"target": "ES2015",
"allowJs": true,
"strict": true
},
"exclude": ["node_modules"]
}
And we use it simply by executing tsc without any parameters since all our
configurations options are specified in the file:
> tsc
TypeScript Gamified | 24
Challenge: Create your First TypeScript Project
Now that we know the basics of TypeScript configuration, we can finally create our
first project!
The goal of this challenge: At the end of this challenge, you’ll have created and
compiled your first TypeScript project.
But this book is all about games! So let’s build a game for our first project. Since we
are just getting started, we won’t try to create anything too fancy. Instead, we’ll make
a function to throw a dice, and you’ll simply have to guess the number.
It’s dangerous to go alone! Let’s face this challenge together, step by step:
You can skip this step if you already have Node.js and NPM installed on your
machine.
To follow this guide, we’ll need to install Node.js and NPM. The easy way to do it is to
download and execute the installer from the official website.
You can also use a version manager like nvm or nvm-windows. This option is
recommended if you want to have multiple versions of Node.js installed on your
machine.
Create a directory called “guess-the-number.” That will be the directory for our entire
project.
NPM init
The first thing we need to do is initialize our project by using the npm init command,
which will create a package.json file where we will define our project’s information,
TypeScript Gamified | 25
dependencies, and more.
Open the terminal, navigate inside the “guess-the-number” directory and execute the
following command:
This command will ask you a few questions. You can leave the default values, except
for “entry point,” where we will set “src/index.ts”. You can also enter your name in the
“author” field.
After finishing the initialization and confirming it, you’ll notice a new file in your
“guess-the-number” directory called package.json . Inside it, you will see all the
properties we set using the npm init command. It should look something like this:
TypeScript Gamified | 26
{
"name": "guess-the-number",
"version": "1.0.0",
"description": "",
"main": "src/index.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "your name",
"license": "ISC"
}
Install TypeScript
The following command will install TypeScript as a Development dependency:
TypeScript Gamified | 27
npx allows us to run packages without the need to install them globally. So
what the previous command does is to execute tsc (the TypeScript compiler
CLI), and as we included the flag --init , it initializes our project with a new
tsconfig.json .
The new tsconfig.json file includes some default configurations and many options
commented out. You can remove the comments, and you’ll be left with this basic
config which is good enough for now:
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
Open the project with VSCode (or your preferred editor) and create a new directory
called “src.” We will add all our code there.
Now, create a new file inside “src” called index.ts . This file will be the starting point
for our game.
TypeScript Gamified | 28
function throwDice() {
const sides = 6;
const randomDiceResult = Math.floor(Math.random() * sides) + 1;
return randomDiceResult;
}
Now we can call this function and check if we have guessed it right:
For the time being, we are going to store our “guess” in a variable since
handling user inputs at this point would be tricky. We’ll get there, don’t worry!
You may have noticed we are not using any specific TypeScript syntax yet because we
are just starting out. But, remember: All JavaScript code is valid TypeScript code!
├───node_modules/
├───src/
│ └───index.ts
├───package-lock.json
├───package.json
└───tsconfig.json
Let’s compile!
Now, let’s see if everything works.
TypeScript Gamified | 29
> npx tsc
You should now see a new file called index.js in the “src” folder. This file is our
index.ts transpiled to JavaScript.
Run it!
We can now run our game with Node!
Congratulations! You have just created and compiled your first TypeScript project .
Bonus challenge!
In the tsconfig.json file, change the target to "es5" . Then, run the compiler again
and see how the resulting index.js file turns out.
This is a simple challenge to get you started with TypeScript. For the Level 2
challenge, we will use type annotations, primitive types, and more to build a
web drawing tool. Keep it up!
TypeScript Gamified | 30
Congratulations!
You just completed the demo version of TypeScript Gamified! You have taken your
first step into the world of TypeScript, and I hope you have enjoyed the journey so
far.
But this is just the beginning. The full book contains five more levels, each with its
own set of challenges to help you master TypeScript even further. From the basics to
more advanced topics, each challenge will guide you through creating a small web or
terminal-based game.
And don’t forget about the bonus challenges! Each challenge includes a bonus round
that will test your skills and provide an extra layer of excitement to your learning
journey.
To help you compare your results I also provide the working code with solutions to
each challenge. So, what are you waiting for? Dive into the full version of TypeScript
Gamified, and let’s take your skills to the next level!
TypeScript Gamified