Penguins in Meetings

The Redwood City Public Library recently hosted a series of workshops on how to make comics. They also asked participants to submit a short comic for publication in an anthology commemorating the 150th anniversary of Redwood City’s founding.

Here’s my submission.

Page 1

Page 2

Page 3

Inked using Adobe Illustrator with a stylus and convertible touch-screeen laptop. I’m still trying to get the hang of it. I like being able to draw directly on the screen (I don’t do so well with generic non-screen tablets). However, a lot of the software out there is still optimized for desktop (e.g. there’s a strong reliance on keyboard shortcuts but using your convertible’s keyboard in tablet mode is awkward). Illustrator has a touch mode, but it currently leaves a lot to be desired (e.g. you can’t access layers in touch mode).

Also, vector illustration software makes convertibles (well, my convertible at least) pretty warm and uncomfortable to hold for long. So it might be worth looking into an iPad Pro + pencil going forward.

Typed Routes with TypeScript

Reposted from the Esper Tech Blog.

Although Esper started out as an OCaml shop, we also use quite a bit of TypeScript to build our front-end. “Why We Use TypeScript” would probably be a long post in and of itself, but this post is about how we use TypeScript to implement a small, open-source library that implements statically-typed route checking.

If you don’t care about the why or how, you can check out said library on Github or download the typed-routes package on NPM.

Routing

By routing, we mean taking some action based on a file-like string path. The path in question is usually a URL, and routing can occur on a web app backend, by the frontend for a single page app, or even by a mobile app.

Probably the most popular way of representing routes in JavaScript-land is an Express-style path (which is typically implemented using the path-to-regexp package). An Express-style path looks like this: /path/to/:arg1/:arg2. It matches /path/to/abc/123, and it captures the third and fourth parts of that path inside a param object that looks like: { arg1: "abc", arg2: "123" }.

This works well enough, but it’s not ideal from a static type-checking perspective. In TypeScript at least, /path/to/:arg1/:arg2 is just a string. There isn’t much it can (currently) do to parse out the parameters. Nor is there much it can do to verify that arg2 is an integer.

[X in keyof S]: S[X] null;
More …

react-redux-set-local

Redux’s dispatch / action / reducer architecture makes it easy to reason about complex state management. Plus the dev tools and overall community support is fantastic.

However, Redux is overkill for state that’s local to a specific component (e.g. is this dropdown open?). Redux’s state management is, by design, independent of React’s component architecture. Separating presentation logic from your state management code is great, but a standard React-Redux implementation (even using the helpful react-redux library) still requires a lot of glue code to hold everything together. Even simple state changes require all of the the following:

  • An action to represent changes to the component state
  • A reducer to apply the action to our store state
  • Code to hook the reducer to the store
  • The React component itself
  • Container code hooking up the React component to code that dispatches our actions

The simplest alternative to this is to just use React’s setState function. But this deprives us of Redux’s dev tools and other benefits.

To address this, I spent part of this weekend writing react-redux-set-local. The name’s a mouthful, so let’s call it RRSL.

More …

Property removals in TypeScript

A quick note about how to easily go from a broader type to a narrower one in TypeScript.

Suppose you have the following two interfaces:

interface ABC {
  a: number;
  b: string;
  c: boolean;
}

interface AB {
  a: number;
  b: string;
}

We want to convert a var from ABC to AB. Although ABC meets all the constraints of AB, the additional excess properties sometimes break things and TypeScript will, sometimes, complain about them.

So we could just do this:

declare var myVar: ABC;
delete myVar.c;

But that’s not really desirable because, assuming TypeScript even lets you do that, you’re mutating an existing typed object. myVar is still typed as ABC, even though it no longer has a c property.

I used to frequently write code that cloned myVar, deleted the extra property, and then typecast the clone to a new interface. But with the introduction of destructuring and spread operator support in TypeScript 2.1, it’s actually quite simple now:

let { c, ...newVar } = myVar

Tada! newVar is created without the c property, and TypeScript recognizes it.