Tic Tac Toe with TypeScript - Part 1
Tags: typescript, tutorial, javascript, beginners
Published: 2020-01-23 12:13:34

##Why TypeScript? 
If you're like me and Javascript is the only programing language you've ever learned you might be a bit repulsed to get into Typescript, at the end of the day your apps work just fine, why would you need to add another layer of complexity to it?

Well, the short answer is... __It makes you a better developer__.
It can also drastically reduce the number of run time bugs you encounter and make the developer experience far better and more efficient (once you get into it).

As always there is a bit of a learning curve to it, and it can really be frustrating sometimes to have your trusted IDE scream at you on every save. But it's a worthwhile tradeoff in the long run.

So without further ado, __let's convert a small app from regular Javascript into its typed superset that is Typescript__ :rocket: 

------
##The setup
For our application, we'll use the Tic Tac Toe we've written in the [last article](https://dev.to/bornasepic/pure-and-simple-tic-tac-toe-with-javascript-4pgn).

If you don't have it already you can grab it from [Github here](https://github.com/BornaSepic/Tic-Tac-Toe).


First things first, we'll need to install Typescript.
You'll first want to position your terminal at the root of the project and run `npm init -y`. This will create our `package.json` file (without asking too many questions :innocent:) and allow us to install typescript via NPM.

Next up we'll run `npm i typescript` to actually install Typescript and all it needs.

I'd recommend moving our project files (`index.html, styles.css, script.js`) into a new folder, just to keep things nice and clean, I've named the folder `src` but that's totally up to you.

This is how the project should look like at this point:
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/wv95xnbttuvy2edwijgy.png)

You'll also want to run `tsc --init`. This will generate our `tsconfig.json` file to allow us to have more control over the TS compiler. 

Before continuing you'll want to change the `// "lib": [],` line in the config file (line 7) and replace it with `"lib": ["es6", "dom", "es2017"],`. This will allow us to use some more advanced features of JavaScript in our code.

To actually get started all we need to do is change our `script.js` into `script.ts`. And run `tsc script.ts` (this will compile our TypeScript file into good old regular JavaScript).
_You've probably gotten an error compiling your `script.ts` file, but that's expected._

Please note we are still only including the `script.js` file in our `index.html`. Since _"TypeScript is a typed superset of JavaScript"_, your browser will never actually run TypeScript. So it a nutshell your users won't notice in any way whether your app is written in TypeScript or not (except for the lack of bugs, and a :smiley: on your face).

------
##Actual TypeScript
Now let's get to the fun part and write ourselves some TypeScript! We'll go through the script line by line and convert what we can to TypeScript.
To keep things nice and "short", for this article we'll just go through the initial variables and finish the app in another one.

In the previous tutorial, we've created some variables that are storing our game state. Let's first take a look at them.
```js
const statusDisplay = document.querySelector('.game--status');

let gameActive = true;
let currentPlayer = "X";
let gameState = ["", "", "", "", "", "", "", "", ""];

const winningMessage = () => `Player ${currentPlayer} has won!`;
const drawMessage = () => `Game ended in a draw!`;
const currentPlayerTurn = () => `It's ${currentPlayer}'s turn`;
```

We first have a `document.querySelector` method that returns an element with the class of 'game--status'. By doing a quick search on [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) we can see that the `.querySelector` returns an Element.
So we'll add a type to our `statusDisplay` variable to let TS know it should contain and Elemenet, like this: 
```js
const statusDisplay: Element = document.querySelector('.game--status');
```

You should be getting an error warning here saying `type 'Element | null' is not assignable to type 'Element'.`

When you think about it this error makes sense, we have no guarantee that the element with a class of "game--status" exists in our DOM. If this was a bigger app we might want to handle this case just to future proof our code but since it's a small application and we know that that element will always be there and we can tell TS that it will never return null by adding an exclamation point to the end, like this:
```js
const statusDisplay: Element = document.querySelector('.game--status')!;
```

Next up we have our `gameActive` variable. Since we know this will only contain a boolean value (either `true` or `false`) we can assign the type of `boolean` to our variable.
```js
let gameActive: boolean = true;
```

After that we have the `currentPlayer` variable. This technically does only contain a string, and there would be nothing wrong with just writing something like:
```js 
let currentPlayer: string = "X";
```

But because we have only two distinct cases here (the variable can only be `"X"` or `"O"`, we can use a more appropriate functionality of TypeScript here called [Enum](https://www.typescriptlang.org/docs/handbook/enums.html). So the end product should look something like this:
```js
enum PlayerSigns {
    X = "X",
    O = "O"
}
let currentPlayer: PlayerSigns = PlayerSigns.X;
```
We have created an Enum that will hold our player signs, and assigned the value of our `currentPlayer` variable to that enum.

After that we have our `gameState` variable, where... we hold our game state (:sunglasses:).

```js
let gameState = ["", "", "", "", "", "", "", "", ""];
```
We can see that this will always be an array of strings, so we can pass that on to our comipler like this: 
```js
let gameState: string[] = ["", "", "", "", "", "", "", "", ""];
```

And lastly, we have our three functions that return our game status messages:
```js
const winningMessage = () => `Player ${currentPlayer} has won!`;
const drawMessage = () => `Game ended in a draw!`;
const currentPlayerTurn = () => `It's ${currentPlayer}'s turn`;
```

Since they are all simple functions, without any inputs, that return strings we can use the same types for all of them.

```js
const winningMessage: () => string = () => `Player ${currentPlayer} has won!`;
const drawMessage: () => string = () => `Game ended in a draw!`;
const currentPlayerTurn: () => string = () => `It's ${currentPlayer}'s turn`;
```

-----
It can seem a bit annoying at times to have to write all the types yourself, but it's another one of those things that become second nature after a brief adjustment period. 

Hopefully, by the end of this series, you'll be convinced on the benefits of using TypeScript for your project.

As always, thanks for reading, and until the next one :v: