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
tsTryconstmethods = {add (a : number,b : number): number {returna +b },}
and in the main application you’d have access to some object with an add automatically (after a connection is established).
tsTrychild .add (3, 4)
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
tslet methods = {add: (a: number, b: number) => a+b,subtract: (a: number, b: number) => a-bdoAsyncThing: (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.
Setup
First, if you haven’t done so already, clone the workshop project for this course
shgit clone https://github.com/mike-north/making-typescript-stickcd making-typescript-stick
Make sure you have Volta installed. If you haven’t done so already, just run the following to install it
shcurl https://get.volta.sh | bash
Next, let’s install our dependencies
shyarn
and finally, let’s navigate to the folder containing this specific challenge
shcd 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.
Hints
- Make sure to brush up on mapped types, conditional types and use of the
inferkeyword - Familiarize yourself with the
Parameters<T>andReturnType<T>utility types