Building Scalable, Maintainable Apps Using TypeScript and React

Kamran Ayub

patterns and practices

๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ ๐Ÿ‘ถ๐Ÿถ

๐ŸŽฒ๐ŸŽฎ๐Ÿ‘จโ€๐Ÿ’ป๐Ÿ“š๐ŸŽธ

Work at Target

What do I want?

To make my apps easier to maintain

To make my apps easier to scale

Scalable

?

Scalable

Easy to extend

ย 

Easy to collaborate on

ย 

Easy to reuse code

Maintainable

Easy to refactor

ย 

Easy to understand

ย 

Easy to test

A familiar story...

TypeScript

JavaScript that scales

  • Static type checking
  • Fantastic editor tooling
  • Refactor-friendly code

React

Component-based presentation

  • Small surface area
  • Reusable components
  • Functional characteristics
  • Great performance

A better way is possible

ktomg.com

  • Built in .NET
  • Hybrid app
  • Originally JavaScript & Knockout.js
  • Migrated to TypeScript & React
  • Heavily interactive UI

Based on a true story

(work in progress)

Concepts

  • Store - Single source of truth for app
  • State - The data representing the app at a point-in-time
  • Actions - Object with a "type" property
  • Action Creators - Small functions that create actions
  • Reducersย - Take actions and update Redux state

Folder Layout

State & Reducers

Actions

Props & State

Action Creators

+ bonus: Jest / CSS-in-JS

Folder layout

(previous)

  • Files are spread out
  • Components folder doesn't scale well
  • Fine for a small site

Folder Layout

Folder layout

(new)

  • Proposed by Ryan Florence
  • Screen organization
  • Scalable nesting
  • Better collaboration
  • Colocate related files
  • Closer imports

Folder Layout

Module Resolution

Not scalable as screens nest further

Folder Layout

Module Resolution

Maintains F12 Go to Definition behavior

Folder Layout

Module Resolution

Folder Layout

Module Resolution

Folder Layout

There's an open issue for emulating "module directories" functionality from Webpack/Jest to allow paths like:

Folder Layout

  • โœ… Scalable folder structure
  • โœ… Avoids ../../ nesting
  • โœ… Supports TypeScript and dev tools

ย 

  • ๐Ÿ˜ No module dirs support yet

Folder Layout

Redux State

"Bottom up" state

State & Reducers

No need to define an entire representative "State" interface. Just export what it will end up being (typeof)

Folder Layout

Redux State

"Bottom up" state

Each screen will define its state shape

State & Reducers

Folder Layout

Redux State

"Bottom up" state

State & Reducers

Folder Layout

Reducers

Combining reducers

State & Reducers

Folder Layout

Reducers

Combining reducers

State & Reducers

Folder Layout

Reducers

Combining reducers

State & Reducers

Folder Layout

Reducers

Combining reducers

State & Reducers

Folder Layout

Reducers

Testing reducers

State & Reducers

Folder Layout

State & Reducers

State & Reducers

  • โœ… Maximizes type inference
  • โœ… "Bottom-up" composable state
  • โœ… Screens manage their own state
  • โœ… Using "shared" folder, you can share state
  • โœ… Using RecursivePartial<T> type helper

Folder Layout

Actions

Using constants and typeof

A bit wordy, but pays off at scale

Actions

Folder Layout

State & Reducers

Actions

Action type helpers

Actions

Folder Layout

State & Reducers

Actions (Discriminated)

Actions

Folder Layout

State & Reducers

Actions (Mapped)

Actions

Folder Layout

State & Reducers

Actions (Mapped)

Creating reducer action map helpers

Actions

Folder Layout

State & Reducers

Actions (Mapped)

Actions

Folder Layout

State & Reducers

Actions

Actions

  • โœ… Strongly-typed actions
  • โœ… Reducer action handlers are typed
  • โœ… Reusable type utilities
  • โœ… If actions or state change, reducers break

Folder Layout

State & Reducers

Action Creators

Action Creators

Folder Layout

Actions

State & Reducers

Action Creators

Dispatching actions

mapDispatchToProps makes it easier to test component in isolation

Action Creators

Folder Layout

Actions

State & Reducers

Action Creators

All type-safe with intellisense

Action Creators

Folder Layout

Actions

State & Reducers

Action Creators

Action Creators

  • โœ… Action creator utility
  • โœ… Dispatch is strongly-typed
  • โœ… Ensure actions invoked with correct args
  • โœ… Testing component is easier
  • โœ… Isolates action signature changes from components

ย 

  • ๐Ÿ˜ย Dispatch typing is wordy, repetitive, annoying

Folder Layout

Actions

State & Reducers

Props & State

(stateful, non-redux)

Props & State

Folder Layout

Actions

Action Creators

State & Reducers

Props & State

(stateless, non-redux)

Folder Layout

Actions

Props & State

Action Creators

State & Reducers

Props & State

(render prop pattern)

Can pull into type alias and share

Folder Layout

Actions

Props & State

Action Creators

State & Reducers

Props & State

(redux state props)

Folder Layout

Actions

Props & State

Action Creators

State & Reducers

Need a way to get "dispatch" and separate Redux state props vs. "own" props

Extract stateless type alias to encapsulate our State and reduce DispatchProp usage

Props & State

(redux state props)

Folder Layout

Actions

Props & State

Action Creators

State & Reducers

Same as stateless, create encapsulated Redux component type

Props & State

(redux class component)

Folder Layout

Actions

Props & State

Action Creators

State & Reducers

Split Redux connected component from "raw" component for easier isolated testing

Props & State

(redux class component)

Folder Layout

Actions

Props & State

Action Creators

State & Reducers

Props & State

Redux type utilities

Folder Layout

Actions

Props & State

Action Creators

State & Reducers

Props & State

Folder Layout

Actions

Props & State

  • โœ… Splitting OwnProps vs. StateProps
  • โœ… Reduce excessive type intersections
  • โœ… Reusable type utilities
  • โœ… Render prop pattern typing
  • โœ… Easier testing of Redux

Action Creators

State & Reducers

BONUS SLIDE

Folder Layout

Actions

BONUS

Action Creators

State & Reducers

Using emotion CSS-in-JS

Doesn't really have any "weirdness" with TypeScript

ย 

For Jest testing and Enzyme, reference the code for deeper examples of async testing / Redux testing

All Together Now!

There's always room for improvement

Thanks for listening!

@kamranayub

kamranicus.com

ย 

Introduction to TypeScript Course

bit.ly/introts

ย 

Midwest.js 2017 Version (Performance Section)

https://youtu.be/owcuEwn-pSM