GoogleChromeLabs / GoogleChromeLabs/comlink

How should I handle optional exposed methods in TypeScript?

Open
#597 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
12.8k
Forks
435
PR merge metrics
No merged PRs in 30d

Description

I would like to expose a common interface for all my workers like this:

```ts
export interface WrappedWorker {
foo?: () => void;
}
```

And one of my workers implements it like this:

```ts
import * as Comlink from "comlink";
import type { WrappedWorker } from "./WrappedWorker.ts";

export class FooWorker implements WrappedWorker {
foo: () => "bar"
}

Comlink.expose(new FooWorker());
```

In my main thread, the wrapped worker will expose `foo` as `Remote<() => string> | Promise`, this causes two problems:

1. `await fooWorker?.foo();` causes lint error for when `foo` is `Promise`.
2. If I resolve the method getter promise before actually calling, comlink proxy will try to `.apply()` to `undefined` and throws. Option 1 throws this one too if `foo` is actually undefined at runtime.

```ts
const worker = new Worker("./WrappedWorker.ts");
const fooWorker = Comlink.wrap(worker);

// 1. Not all constituents of type 'Promise | Remote<() => Promisable>' are callable.
await fooWorker?.foo();

// 2. TypeError: Cannot read properties of undefined (reading 'apply')
const fooMethod = await fooWorker.foo;
await fooMethod?.();
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.