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

type safety + front-end code =

type safety + front-end code =

A brief motivation for the importance of static type safety in larger codebases. Comparison of different static type-checkers options for front-end code: TypeScript, Flow, Reason, Elm. Trade-offs and recommendations.

6923aa25bf3f00c27df529c4419daf94?s=128

Kenneth Skovhus

June 15, 2017
Tweet

Transcript

  1. TYPE SAFETY + FRONT-END CODE = @KENNETH_SKOVHUS COPENHAGEN.JS JUNE 2017

  2. I’VE HAPPILY INTRODUCED TYPE SAFETY (ALONGSIDE FEATURES/BUGS) AT

  3. JAVASCRIPT STATUS UPDATE

  4. None
  5. ES2015 ES2016 ES2017 THE LANGUAGE IS EVOLVING! PROCESS GOVERNED BY

    TC39 (TECHNICAL COMMITTEE 39)
  6. COMPILER ~ TRANSPILER

  7. COMPLEXITY ☝ SINGLE PAGE WEB APPS NATIVE MOBILE APPS DESKTOP

    APPS NODE APPS
  8. CODEBASES LARGER THAN WE CAN KEEP IN OUR MIND...

  9. STATIC TYPE CHECKING TO THE RESCUE?

  10. STATIC TYPE CHECKING?

  11. TYPE SAFETY IS THE EXTENT TO WHICH A PROGRAMMING LANGUAGE

    DISCOURAGES OR PREVENTS TYPE ERRORS.
  12. function Greeter({name}) { return ( <h1>Hello, {name}</h1> ); } Greeter.propTypes

    = { name: PropTypes.string }; REACT PROPTYPES EXCELLENT GATEWAY DRUG INTO STATIC TYPES ENFORCED COMPILE TIME INSTEAD OF RUNTIME?
  13. CAPTURE ERRORS COMPILE TIME SMARTER TOOLING (E.G. AUTO COMPLETION) MAKE

    REFACTORING LESS SCARY DOCUMENT THE INHERENT TYPES A SYSTEM A STATIC TYPE CHECKER SHOULD
  14. COMPILE TIME ERRORS > RUNTIME

  15. SHOW ME THE OPTIONS!

  16. MICROSOFT TYPESCRIPT FIRST RELEASED 2012, ANDERS HEJLSBERG (C#) SUPERSET OF

    JAVASCRIPT (ES2016+) TYPE ANNOTATIONS, ENUMS, CLASS INTERFACES COMPILER / TYPECHECKER / BUNDLER LOTS OF LIBRARY DEFINITIONS USERS: ANGULAR 2, VS CODE, ...
  17. FIRST RELEASED 2014 TYPESCRIPT-LIKE ANNOTATIONS FOR JS (OPT-IN) ONLY A

    POWERFUL TYPE CHECKER USE BABEL OR * AS COMPILER, WEBPACK OR * AS BUNDLER USERS: FACEBOOK, REACT, REACT-NATIVE FACEBOOK FLOW
  18. function greeter(person) { return "Hello, " + person; } const

    user = [0, 1, 2]; document.bodi.innerHTML = greeter(user); PLAIN JS
  19. function greeter(person: string) { return "Hello, " + person; }

    const user = [0, 1, 2]; document.bodi.innerHTML = greeter(user); tsc greeter.ts greeter.ts(8,15): error TS2339: Property 'bodi' does not exist on type 'Document'. greeter.ts(8,35): error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'. TYPESCRIPT
  20. /* @flow */ function greeter(person) { return "Hello, " +

    person; } const user = [0, 1, 2]; document.bodi.innerHTML = greeter(user); FLOW flow check greeter-flow.js:3 3: return "Hello, " + person; ^^^^^^ array literal. This type cannot be added to 3: return "Hello, " + person; ^^^^^^^^^^^^^^^^^^ string greeter-flow.js:8 8: document.bodi.innerHTML = greeter(user); ^^^^ property `bodi`. Property not found in 8: document.bodi.innerHTML = greeter(user); ^^^^^^^^ Document
  21. COMPILE TIME ERRORS > RUNTIME

  22. function greeter(person: string) { return "Hello, " + person; }

    const user = "John"; document.body.innerHTML = greeter(user); EASY DEBUG-ABLE OUTPUT MATTERS! function greeter(person) { return "Hello, " + person; } const user = "John"; document.body.innerHTML = greeter(user); FLOW & TYPESCRIPT
  23. IS JAVASCRIPT + TYPES THE ANSWER?

  24. NEW LANGUAGE! PURE SCRIPT ELM IS JAVASCRIPT + TYPES THE

    ANSWER? EXISTING LANGUAGE 2 JS! SCALA.JS CLOSURESCRIPT BUCKLESCRIPT (OCAML)
  25. FIRST APPEARED 2012 REASON: SYNTAX & TOOLCHAIN FOR OCAML OCAML:

    EXCELLENT TYPE INFERENCE (NO TYPE DECLARATION BLOAT) BUCKLESCRIPT: COMPILES OCAML TO FAST/SIMPLE JS VERY EARLY STAGES... POPULAR USERS: MESSENGER.COM (~30%) FACEBOOK REASON + BUCKLESCRIPT
  26. FIRST APPEARED 2012 PURELY FUNCTIONAL LANGUAGE DOMAIN-SPECIFIC STANDARD LIB FOR

    WEB APPLICATIONS SUPER USER FRIENDLY TOOLING & ECO SYSTEM THE ELM ARCHITECTURE POPULAR USERS: PREZI? ELM
  27. let greeter = fun name => "Hello, " ^ name;

    let user = [1, 2, 3]; /* Tried bs-webapi and bs-dom... */ REASON + BUCKLESCRIPT
  28. import Html exposing (text) greeter person = "Hello, " ++

    person main = text (greeter [0, 1, 2]) ELM elm make Greeter.elm -- TYPE MISMATCH --------------------------------------------------- Greeter.elm The argument to function `greeter` is causing a mismatch. 7| greeter [0, 1, 2]) ^^^^^^^^^ Function `greeter` is expecting the argument to be: String But it is: List number Detected errors in 1 module.
  29. HELLO LANGUAGE THAT LOOKS NOTHING LIKE JS! GOODBYE EASY DEBUG-ABLE

    OUTPUT (GOODBYE EXIT STRATEGY)
  30. None
  31. None
  32. COMPILE TIME ERRORS > RUNTIME

  33. SILVER BULLET!

  34. None
  35. INTRODUCING TYPES = TEARS & BLOOD

  36. TRADE-OFFS! MAKE CODE HACKABLE VS RIGID BUT SAFER

  37. BUT PAYS OFF FOR SYSTEMS WITH: · A CERTAIN SIZE/COMPLEXITY

    · MULTIPLE CONTRIBUTORS
  38. SO, WHAT SHOULD I BET ON?

  39. FACEBOOK FLOW MICROSOFT TYPESCRIPT FACEBOOK REASON ELM CLOSURE

  40. FACEBOOK FLOW MICROSOFT TYPESCRIPT FACEBOOK REASON ELM CLOSURE

  41. TYPE SAFE FRONT-END CODE RECOMMENDATIONS? GREEN FIELD WEBSITE → FLOW

    / TYPESCRIPT OR ELM GREEN FIELD NODE PROJECT → FLOW / TYPESCRIPT GREEN FIELD REACT NATIVE → FLOW EXISTING CODEBASE (WEB, NODE, REACT NATIVE) → FLOW / TYPESCRIPT
  42. A FEW TIPS FOR FLOW + REACT / REDUX

  43. CONFIG REDUCER & ACTIONS REDUX DOCUMENT REDUCER & ACTIONS PUBLISHER

    REDUCER & ACTIONS USER REDUCER & ACTIONS … REDUCER & ACTIONS
  44. CONFIG REDUCER & ACTIONS + TYPES REDUX DOCUMENT REDUCER &

    ACTIONS + TYPES PUBLISHER REDUCER & ACTIONS + TYPES USER REDUCER & ACTIONS + TYPES … REDUCER & ACTIONS + TYPES
  45. REDUX USER/REDUCER.JS const initialState = { token: null, userId: null,

    }; function reducer(state = initialState, action) { switch (action.type) { case “USER/SET_USER_ID”: return { ...state, userId: action.id }; ...
  46. REDUX USER/REDUCER.JS /* @flow */ import type { Action }

    from ‘../types’; export type State = {| +token: ?string, +userId: ?number, |}; const initialState = { token: null, userId: null, }; function reducer(state: State = initialState, action: Action) { switch (action.type) { case “USER/SET_USER_ID”: return { ...state, userId: action.id }; ...
  47. function Greeter({name}) { return ( <h1>Hello, {name}</h1> ); } Greeter.propTypes

    = { name: PropTypes.string }; REACT PROPTYPES CODEMOD-PROPTYPES-TO-FLOW
  48. function Greeter({name}: Props) { return ( <h1>Hello, {name}</h1> ); }

    type Props = { name: ?string }; REACT PROPTYPES flow src/components/App.js:31 <Greeter name={[1, 2, 3]} /> ^^^^ props of React element `Greeter`. This type is incompatible... CODEMOD-PROPTYPES-TO-FLOW
  49. TYPE SAFETY + FRONT-END CODE = @KENNETH_SKOVHUS COPENHAGEN.JS JUNE 2017

  50. QUESTIONS? @KENNETH_SKOVHUS COPENHAGEN.JS JUNE 2017

  51. THANKS! @KENNETH_SKOVHUS COPENHAGEN.JS JUNE 2017