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)

7dce9b480f93b02761519348359c4b71?s=128

Patrick Stapfer

September 14, 2017
Tweet

More Decks by Patrick Stapfer

Other Decks in Programming

Transcript

  1. None
  2. None
  3. https://github.com/amazeeio/lagoon

  4. None
  5. None
  6. None
  7. None
  8. None
  9. None
  10. None
  11. 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);
  12. None
  13. None
  14. None
  15. None
  16. None
  17. None
  18. None
  19. None
  20. None
  21. None
  22. None
  23. None
  24. None
  25. None
  26. None
  27. None
  28. None
  29. None
  30. None
  31. 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" }
  32. 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" };
  33. "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
  34. 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)
  35. 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`; };
  36. 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;
  37. let convertData {board, progress} :ticTacToeState => { board: parseBoard board,

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

    |> then_ (fun text => try (parseGameJsonExn text |> resolve) { | ex => reject ex }) ); function fetchData (): Promise<ticTacToeState>
  39. // 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} => { ... } };
  40. ... 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> ...
  41. None
  42. 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> };
  43. http://github.com/ryyppy/reason-lnd Source Code for TicTacToe App + Server:

  44. None
  45. None