Flow Cookbook

Gotchas and interesting cases of flow issues
Gotchas and interesting cases of flow issues
This is a platform for User Generated Content. G/O Media assumes no liability for content posted by Kinja users to this platform.

Typing Promises to Avoid Issues with Fallbacks

When creating Promises, it’s a good practice not to fail the rendering of the entire page because fetching something that is not essential to a given page failed for whatever reason. In these cases, we provide fallbacks in catch handlers, like an empty object in the case of a replyCount api call. We should still be able to display the frontpage if the comments service is down and we weren’t able to fetch the reply count of posts. So let’s say that the default return type of the call is Promise<{ [PostId]: number }> and in the catch handler we default to an empty object: Promise.resolve({}) .

Illustration for article titled Typing Promises to Avoid Issues with Fallbacks
Advertisement

There’s a problem with this. Since we didn’t explicitly define the type of replyCountsPromise, flow infers it. And what it does is looks at all the possibilities of what shape it can take, and merges them together into a union. This is how we get the type of Promise<{ [PostId]: number } | {||}> .

This can lead to all kinds of trouble when we try to access a value in the resulting dataset. Flow will complain that

Cannot access computed property using `PostId` [1].

This can be a bit confusing, you might think there’s an issue with the typing of one of the variables involved, but it turns out the culprit is the exact empty object type that flow inferred.

Advertisement

To solve this, either type the empty object by casting it, or, even better, give an explicit type to replyCountsPromise!

Illustration for article titled Typing Promises to Avoid Issues with Fallbacks
Advertisement

Now flow will know that in all branches of the Promise the return value is the same.

The Marciverse awaits

Share This Story

Get our newsletter