Instantly share code, notes, and snippets.

# busypeoples/Flow_Chapter_One.md

Last active Jul 11, 2018
Chapter 1: Using Flow

# Back To The Basics

## Chapter 1: Using Flow

### Introduction

Why does it make sense to use FlowType or TypeScript when working with JavaScript? A good approach in answering this question is to build a small game or application to make the benefits clear.

So here it is. Part One. We will build TicTacToe in Javascript. Although it might sound trivial or too simple, it will enable us to see how we can leverage FlowType to make our application more predictable and reliable.

### Getting Started

If you don't have Flow installed yet, check the installation guide.

So let's begin with thinking about how we want to structure our game. First of all, we will need a board, remember it's 3x3 fields that we will need. Should we model it as an array containing 3 rows (containing 3 cells each) or as a flat list containing 9 cells?

The are benefits and tradeoffs to both approaches. Modelling it as a flat list gives the advantage to quickly retrieve and update any cell, by accessing the list via indexes. The disadvantage is that we can't be sure that someone might be changing the structure by appending or removing a cell. With the rows approach we gain the ability to model the board to reflect the exact structure. Three rows containing three cells. On the other hand we will need to do more transformation work when accessing or updating a cell.

To make it impossible to define an arbitrary structure, we will take the explicit route.

First of all let's define a `Cell` type, the smallest unit we will neeed. A `Cell` can either be a Circle, a Cross or Empty. So let's define all the possible types.

```type Circle = {type: 'Circle'}
type Cross = {type: 'Cross'}
type Empty = {type: 'Empty'}

type Cell
= Circle
| Cross
| Empty```

Just by looking at the `Cell` type, we can see what the possible types are.

Now that we have the `Cell` type defined, we can continue and add `Row` and `Board` types.

```type Row = [Cell, Cell, Cell]
type Board = [Row, Row, Row]```

These type definitions are self explanatory. We can see that a `Board` consists of three rows.

Now that we have type definitions in place, let's start to build the game. We will use React to render the game to the screen. First off, let's just write a component that renders "TicTacToe".

```import React from 'react'
import { render } from 'react-dom'

class TicTacToe extends React.Component<any> {
render() {
return <div>TicTacToe</div>
}
}

render(<TicTacToe />, document.getElementById('root'))```

Good. We can start to build up the game as we have an entry point now. One interesting thing to note is that we needed to give Flow a type definition for the React Component `class TicTacToe extends React.Component<any>`. For now we can pass `any` to prevent Flow from complaining, but we will refine the definition as we move further in our implementation.

### The Board

It's time to build the board. Our TicTacToe component will keep state of the current game status as well as the board. The status includes which players turn it is as well as if the game has ended and if there is a winner. We will need to keep track of this information as the view has to reflect these facts.

So, next let's define a `Player` type, which we can trivially model as 0 or 1.

`type Player = 0 | 1`

What's still missing is defining the actual game status, is the game still active, has it ended and do we have a winner. Here's a try at a possible definition:

`type Status = Result | {type: 'Running'}`

What can `Result` be? It either contain a winner or no winner at all and the fact that the game has ended. Let's add a `Maybe` type that can be paramerized.

`type Maybe<A> = Just<A> | Nothing`

And `Just` and `Maybe` can be defined like so:

```type Just<A> = {type: 'Just', result: A}
type Nothing = {type: 'Nothing'}```

Now we can check the type later in the code and react acordingly.

So our `Result` can be defined as:

`type Result = Maybe<[Player, Row]>`

This might look confusing at first, but we're actually defining a tuple containing a Player and a Row. By doing so, we can highlight the winning combination and the player and display these facts on the screen. In case the game has finished but there is no winner, the `Nothing` type will be the indicator.

Now that we have everything in place, let's render an empty board next. Our TicTacToe component will need an initial state. So let's also define the component's state shape.

```type State = {
board: Board,
player: Player,
status: Status
}```

We should tell our Compoenent what the state shape is. If we take a look at the Flow documentation, we will notice that we can pass in a prop and a style definition. `Component<Props, State>`. We don't have any props, so we'll just use a placeholder and define the `State shape.

`class TicTacToe extends React.Component<*, State>`

So let's add our initial state.

```class TicTacToe extends React.Component<*, State> {
state = {
board: [],
status: {type: 'Running'},
player: 0,
}
...
}```

Flow will complain:

```board: [],
^^ empty array literal. Tuple arity mismatch. This tuple has 0 elements and cannot flow to the 3 elements of
board: Board,
^^^^^ tuple type```

So let's fix this by defining a row contianing three empty rows.

```const empty : Empty = {type: 'Empty'}
const emptyRow : Row = [empty, empty, empty]
const board : Board = [emptyRow, emptyRow, emptyRow]```

And updating our initial state accordingly.

```class TicTacToe extends React.Component<*, State> {
state = {
board: board,
status: {type: 'Running'},
player: 0,
}
...
}```

So this already great. We finally have defined our initial state and are ready to actually render the board now.

```class TicTacToe extends React.Component<*, State> {
state = {
board: board,
status: {type: 'Running'},
player: 0,
}
render() {
const {board} = this.state
return <div>{
board.map((row, i) => {
return <div style={{width: '600px', height: '150px'}} key={i}>
{row.map((cell, j) => {
return <div style={{
float: 'left',
textAlign: 'center',
border: '1px solid #eee',
}} key={j}>
cell
</div>
})}
</div>
})
}</div>
}
}```

Neglect the styling part for now, but you can see that we map over the `board` array first and then map over the `row` array to display the cells. For now we will only render the word 'cell'.

Our next steps will include refactoring the board and cells to their own respective components and we will add interactivity, so player's can take turn and start playing.

Although it seems like a lot of work is involved upfront for definining and displaying a simple 3 x 3 board, we can already guarantee that the board has 3 rows containing 3 cells. Try to define a different shape and Flow will complain.

`const board : Board = [emptyRow, emptyRow, null]`

Flow tells us that we have a mismatch.

```const board : Board = [emptyRow, emptyRow, []]
^^ empty array literal. Tuple arity mismatch. This tuple has 0 elements and cannot flow to the 3 elements of
type Board = [Row, Row, Row]
^^^ tuple type```

### Summary

That's it for part one. In the next part we will see more benefits by defining everything upfront.

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 // @flow // Example implementation from Chapter One import React from 'react' import { render } from 'react-dom' type Circle = {type: 'Circle'} type Cross = {type: 'Cross'} type Empty = {type: 'Empty'} type Cell = Circle | Cross | Empty type Row = [Cell, Cell, Cell] type Board = [Row, Row, Row] type Player = 0 | 1 type Just = {type: 'Just', result: A} type Nothing = {type: 'Nothing'} type Maybe = Just | Nothing type Result = Maybe<[Player, Row]> type Status = Result | {type: 'Running'} type State = { board: Board, player: Player, status: Status } const empty : Empty = {type: 'Empty'} const emptyRow : Row = [empty, empty, empty] const board : Board = [emptyRow, emptyRow, emptyRow] class TicTacToe extends React.Component<*, State> { state = { board: board, status: {type: 'Running'}, player: 0, } render() { const {board} = this.state return
{ board.map((row, i) => { return
{row.map((cell, j) => { return
cell
})}
}) }
} } render(, document.getElementById('root'))