Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Road to a Statically Typed Future Pt.2

The Road to a Statically Typed Future Pt.2

JavaScript's dynamic nature and rich and expressive syntax are strengths of the language, making it an approachable and beginner-friendly language to get started with. However, this same flexibility through dynamic typing and runtime evaluation increases the difficulty of debugging and makes it tough to confidently change existing code.

This talk will discuss Patrick's personal journey and experience on using existing type systems within and outside of the JavaScript ecosystem, specifically Flow and ReasonML, and demonstrate how they can improve your workflow.

Patrick will talk about general concepts of why we need type definitions, how types will influence API designs, the differences between static and runtime types and how we can bridge the gap between a statically compiled, type-safe language and the JavaScript ecosystem.

This presentation is based on Pt.1 of this presentation series... in Pt. 2 he will demo how types will translate from the Flow type checker to the ReasonML language by using a practical example.

Presented at:

- 14th of September 2017 (JavaZone - Oslo)
- 23rd of September 2017 (Frontend Connect - Warsaw)
- 30th of September 2017 (ReactAlicante)

Patrick Stapfer

September 14, 2017
Tweet

More Decks by Patrick Stapfer

Other Decks in Programming

Transcript

  1. const toSiteHostStr = (obj) => R.compose( R.ifElse( R.compose( // (val)

    => val.length > 1, R.lt(1), R.length ), R.join('.'), R.compose(R.always('')) ), R.values, R.pick(['serverIdentifier', 'serverInfrastructure']) )(obj);
  2. type State = { board: Board, progress: Progress, }; type

    Token = "X" | "O" | "Empty"; type Board = Array<Token>; type Player = "X" | "O"; type Progress = 
 { type: "turn", player: Player } | { type: "win", player: Player } | { type: "draw" }
  3. Types in Action switch (game.type) { case "turn": const {player}

    = game; return `Player ${player}'s turn`; case "win": const {player} = game; return `Player ${player} won`; }; const game: Game = { type: "turn", player: "X" };
  4. "Pattern Matching" in Flow switch (game.type) { case "turn": const

    {player} = game; return `Player ${player}'s turn`; case "winner": const {player} = game; return `Player ${player} won`; }; switch is no expression game = objects flow infer is brittle typoooooos No checks for exhaustiveness verbose syntax
  5. Let's design the model in Reason! type ticTacToeState = {

    board: board progress: progress, }; type token = | X | O | Empty type player = | X | O type progress = 
 | Turn player
 | Win player
 | Draw type board = (row, row, row) type row = (token, token, token)
  6. Model Types in Action (Reason) switch (game) { | Turn

    p => "Player" ^ (p_to_str p) ^ "'s turn" | Win p => "Player" ^ (p_to_str p) ^ "won" | Draw => "It's a draw!" }; let game = Turn X; switch (game.type) { case "turn": const {player} = game; return `Player ${player}'s turn`; case "win": const {player} = game; return `Player ${player} won`; };
  7. let parseGameJsonExn text => Js.Json.parseExn text |> (fun json =>

    Json.Decode.{ board: field "board" (array (array string)) json, progress: field "progress" (array string) json }) |> convertData;
  8. let convertData {board, progress} :ticTacToeState => { board: parseBoard board,

    progress: parseProgress progress }; function convertData(obj: { board: Array<Array string>, progress: Array<string> }): TicTacToeState
  9. let fetchData () => Js.Promise.( fetch "/load" |> then_ Response.text

    |> then_ (fun text => try (parseGameJsonExn text |> resolve) { | ex => reject ex }) ); function fetchData (): Promise<ticTacToeState>
  10. // src/ticTacToe.re open Game; type action = | PlayTurn selection

    | Restart; type state = ticTacToeState; let component = ReasonReact.reducerComponent "TicTacToe"; let make ::board=? ::progress=? _children => { ...component, initialState: fun () => { ... }, reducer: fun action state => switch action { | PlayTurn s => ReasonReact.Update (playTurn state s) | Restart => ReasonReact.Update (initialState ()) }, render: fun {state, reduce} => { ... } };
  11. ... render: fun {state, reduce} => <div className="game"> <div className="game-board">

    <Board rows=state.board handleSquareClick=( reduce (fun selection => PlayTurn selection) ) /> </div> ( switch state.progress { | Turn p => renderCurrentPlayer p | Win p => renderWin p (reduce (fun _evt => Restart)) | Draw => renderDraw (reduce (fun _evt => Restart)) } ) </div> ...
  12. type props = { value: token, handleClick: ReactEventRe.Mouse.t => unit

    }; let component = ReasonReact.statelessComponent "Square"; let squareStyle = ReactDOMRe.Style.make width::"25px" fontSize::"100pt" (); let make ::value ::handleClick _children => { ...component, render: fun _self => <span style=squareStyle onClick=handleClick> ( switch value { | Cross => <div> X </div> | Circle => <div> O </div> | Empty => <div/> } ) </span> };