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

Typesafe(ish) React

Typesafe(ish) React

Static type-checking via tools like TypeScript or Flow can help reveal implementation errors before the app goes down. This presentation looks at what these tools are—and aren't—and how you can use them to build safer, saner React applications.

0b7fb38ae0407a97f5a342ebbcc288f7?s=128

RJ Zaworski

October 10, 2018
Tweet

Transcript

  1. Typesafe(ish) React RJ Zaworski director of growth, koan.co · @rjzaworski

    · github.com/rjz
  2. “ Types ...tell the compiler or interpreter how the programmer

    intends to use the data” (https://en.wikipedia.org/wiki/Data_type, http://bit.ly/2C09A0w)
  3. “ Type safety ...the extent to which a programming language

    discourages or prevents type errors” > const sayHello = "I'm a string."; > sayHello(); TypeError: sayHello is not a function (https://en.wikipedia.org/wiki/Type_safety)
  4. Type checks ★ Static v. dynamic (when is check made?)

    ★ Strong v. weak (how strict is it?) Dynamic Static Weak JavaScript C (sort of) Strong Python, Ruby Flow, Reason, TypeScript
  5. JavaScript is everywhere.

  6. JavaScript is everywhere.

  7. When it breaks Read & parse Static checks Linting Compile

    Formatting Test? Run Type checking
  8. None
  9. Imagine if... Read & parse Static checks Linting Compile Formatting

    Test? Type-checking Run
  10. TypeScript

  11. Motivations ★ Catch issues early ★ Ship features, not bugs

    ★ Make assumptions explicit
  12. Why TypeScript? Good! ★ Superset of JS ★ ESNext included

    * ★ Performance ★ Community But... ★ Superset of JS ★ Integration with existing projects ★ Consider alternatives * YMMV
  13. Hello, world! 1. Install $ npm install -g typescript 2.

    Compile $ tsc --strict point.ts 3. Run $ node point.js { x: 3, y: 4 } type Point = { x: number, y: number, }; const add = (p1: Point, p2: Point): Point => ({ x: p1.x + p2.x, y: p1.y + p2.y, }); const p: Point = { x: 1, y: 1 }; const o: Point = { x: 2, y: 3 }; console.log(add(p, o)); point.ts
  14. Hello, world! Even good programmers do bad things... $ tsc

    point.ts point.ts:8:3 - error TS2339: Property 'z' does not exist on type 'Point'. 8 p.z = 42; ~ type Point = { x: number, y: number, }; const p: Point = { x: 1, y: 1 }; p.z = 42; point.ts
  15. Interfaces ★ Define data shape ★ Extensible interface Bounds {

    readonly w: number, // width readonly h: number, // height area(): number, } function square (a: number) { return { h: a, w: a, area: () => a * a, }; } function perimeter (b: Bounds) { return 2 * (b.w + b.h); } interface.ts h w area()
  16. Generics ★ Reusable ★ Type-independent type Circle = Bounds &

    { readonly r: number, } function circle (r: number) { const area = () => Math.PI * r * r; return { r, h: r + r, w: r + r, area }; } const mapper = <T, U>(f: (t: T) => U) => (ts: T[]) => ts.map(f); const circleMapper = mapper<number, Circle>(circle); const circles = circleMapper([1, 2, 3]); generics.ts h w r
  17. React

  18. Getting started 1. Scaffold $ npx create-react-app myapp \ --scripts-version=react-scripts-ts

    2. Install some dependencies $ npm i redux $ npm i react-redux 3. And some @types $ npm i @types/react-redux
  19. Yet another todo list™ (http://tspirates.surge.sh/; https://github.com/rjz/tspirates)

  20. Stateless Consider… interface StatelessComponent<P> { (props: P, context?: any): ReactElement<any>;

    // ... }; type SFC<P> = StatelessComponent<P> import * as React from 'react'; type GameProps = { outcome: string, shipsSunk: number, ]; const GameView: React.SFC<GameProps> = (props) => ( <div> outcome: {props.outcome}<br /> shipsSunk: {props.shipsSunk}<br /> </div> ); GameView.ts
  21. Stateful Consider… class Component<P, S> { // ... state: readonly<S>;

    render(): ReactNode; } class App extends React.Component<{}, { outcome: string, shipsSunk: number, }> { state = { outcome: 'PENDING', shipsSunk: 0, }; render() { return <GameView {...this.state} />; } } App.ts
  22. Events DOM types? interface MouseEvent<T = Element> extends SyntheticEvent<T> {

    clientX: number; clientY: number; // ... } onClick = (e: React.MouseEvent) => fireCannonAt({ x: e.clientX, y: e.clientY, }); render() { return ( <div onClick={this.onClick}> <GameView {...this.state} /> </div> ); } App.ts
  23. Thank you! rj zaworski · @rjzaworski · github.com/rjz

  24. Further Reading ★ www.typescriptlang.org/ ★ github.com/DefinitelyTyped/DefinitelyTyped