Is it safe to ignore TS errors for promise pipelining?

I am trying to better understand RPC promise pipelining and the using directive from the [docs],(https://developers.cloudflare.com/workers/runtime-apis/rpc/#promise-pipelining) but I'm getting a typescript error Im not sure what to do about. I know RPC endpoints don't return promises so is this safe to ignore (ie is it a result of ts not knowing the difference between an RPC stub and an actual promise)? The error I get is:
The initializer of a 'using' declaration must be either an object with a '[Symbol.dispose]()' method, or be 'null' or 'undefined'.ts(2850)
The initializer of a 'using' declaration must be either an object with a '[Symbol.dispose]()' method, or be 'null' or 'undefined'.ts(2850)
Here is my basic counter service whicih is the callee:
import { RpcTarget, WorkerEntrypoint } from "cloudflare:workers";

class Counter extends RpcTarget {
#value = 0;

increment(amount: number) {
this.#value += amount;
return this.#value;
}

get value() {
return this.#value;
}
}

export class CounterService extends WorkerEntrypoint {
async newCounter() {
return new Counter();
}
}

export default {
fetch() {
return new Response("ok");
},
};
import { RpcTarget, WorkerEntrypoint } from "cloudflare:workers";

class Counter extends RpcTarget {
#value = 0;

increment(amount: number) {
this.#value += amount;
return this.#value;
}

get value() {
return this.#value;
}
}

export class CounterService extends WorkerEntrypoint {
async newCounter() {
return new Counter();
}
}

export default {
fetch() {
return new Response("ok");
},
};
....and here is my caller/client worker:
export default {
async fetch(_request: Request, env: Env) {
// Only one round trip! Note the missing `await`.
using promiseForCounter = env.COUNTER_SERVICE.newCounter();
await promiseForCounter.increment(10);

return new Response("client-worker online");
},
};
export default {
async fetch(_request: Request, env: Env) {
// Only one round trip! Note the missing `await`.
using promiseForCounter = env.COUNTER_SERVICE.newCounter();
await promiseForCounter.increment(10);

return new Response("client-worker online");
},
};
If we add an await the error goes away (which would make it 2 network hops) and if we make it const instead of using it also goes away.
4 Replies
Jakov
Jakov3mo ago
I recommend adding // @ts-expect-error comment
darkpool
darkpoolOP3mo ago
So the error is a result of ts not knowing the difference between an RPC stub and an actual promise?
Jakov
Jakov3mo ago
Yes, The RPC stub returned by env.COUNTER_SERVICE.newCounter() doesn't have a [Symbol.dispose] method in its type definition, so TypeScript correctly flags it as an error according to the standard rules of the language. ​However, the Cloudflare Workers runtime overloads this syntax. It sees using applied to an RPC stub and uses it to manage the lifecycle of the remote object and, crucially, to batch subsequent method calls on that stub into a single network request.
darkpool
darkpoolOP3mo ago
awesome, thanks for the explanation!

Did you find this page helpful?