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

The Road to a Statically Typed Future (ReactAlicante 2017)

The Road to a Statically Typed Future (ReactAlicante 2017)

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 on:
- 30th of September 2017 (React Alicante 2017)

7dce9b480f93b02761519348359c4b71?s=128

Patrick Stapfer

September 30, 2017
Tweet

Transcript

  1. September 2017 The Road to a Statically Typed Future Patrick

    Stapfer
  2. Thanks to our sponsors!

  3. None
  4. None
  5. https://github.com/amazeeio/lagoon

  6. None
  7. None
  8. None
  9. None
  10. None
  11. None
  12. None
  13. 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);
  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. None
  32. None
  33. 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" }
  34. Types in Action switch (progress.type) { case "turn": const {player}

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

    {player} = progress; return `Player ${player}'s turn`; case "winner": const {player} = progress; return `Player ${player} won`; }; switch is no expression progress = typeof Object flow infer is brittle typoooooos No checks for exhaustiveness verbose syntax
  36. 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)
  37. Model Types in Action (Reason) switch (progress) { | Turn

    p => "Player" ^ (p_to_str p) ^ "'s turn" | Win p => "Player" ^ (p_to_str p) ^ "won" | Draw => "It's a draw!" }; let progress = Turn X; switch (progress.type) { case "turn": const {player} = progress; return `Player ${player}'s turn`; case "win": const {player} = progress; return `Player ${player} won`; };
  38. 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;
  39. let convertData {board, progress} :ticTacToeState => { board: parseBoard board,

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

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

  46. None
  47. None