Learn TypeScript w/ Mike North

Challenge 4: Penpal types

March 22, 2022

Table of Contents

The Challenge

Years ago I was doing some work that involved Web Workers. If you’ve never used these before, you can think of them as totally independent programs that communicate with your “main” program via the postMessage API.

postMessage is great (and a good example of the actor concurrency model) but it’s not the most refined way to handle asynchronous communication. Frankly, I prefer Promises!

Thankfully I found this cool open source project called Penpal, which effectively allows you to define methods in your worker, and they appear in your main application async-ified.

For example, in your worker you might have

const methods = {
add(a: number, b: number): number {
return a + b

and in the main application you’d have access to some object with an add automatically (after a connection is established).

child.add(3, 4)
(property) add: (a: number, b: number) => Promise<number>

If the way this works is not quite clear to you, I recommend taking a look at the readme for the library

The task

Create a utility type WrapForPenpal<T> that takes an object T with methods (you may assume no non-function properties are ever on this object), and emits a type with similar methods, but any non-promise return types become ”Promise-ified”.

For example

let methods = {
add: (a: number, b: number) => a+b,
subtract: (a: number, b: number) => a-b
doAsyncThing: (url: string): Promise<string[]>
const asyncMethods: WrapForPenpal<typeof methods> = {}
asyncMethods.add(a, b); // returns Promise<number>
asyncMethods.subtract(a, b); // returns Promise<number>
asyncMethods.doAsyncThing('/api/thing'); // Promise<string[]>

You do not need to worry about actually creating an object that has these Promise-ified methods — we are only interested in the utility type.


First, if you haven’t done so already, clone the workshop project for this course

git clone https://github.com/mike-north/making-typescript-stick
cd making-typescript-stick

Make sure you have Volta installed. If you haven’t done so already, just run the following to install it

curl https://get.volta.sh | bash

Next, let’s install our dependencies


and finally, let’s navigate to the folder containing this specific challenge

cd challenges/async-communicator

Your job is to modify the code in ./src/index.ts until all of the existing tests within the same file pass.


© 2022 All Rights Reserved