cloudflare / cloudflare/capnweb
document tsconfig `lib`/`target` requirements
- Dominant language
- TypeScript
- Stars
- 4k
- Forks
- 143
- Avg merge
- 4d 6h
- Merged PRs (30d)
- 7
Description
## Description
When using `newWebSocketRpcSession` or `newHttpBatchRpcSession` with a TypeScript generic parameter, the `RpcStub` type preserves primitive return types (string, number, boolean) but fails to preserve object/interface return types, returning `any` instead.
## Minimal Reproducible Example
```typescript
import { newWebSocketRpcSession, type RpcStub } from 'capnweb';
// Define types
type ApiMessage = { message: string; timestamp: string };
// Define API interface
interface MyApi {
getPrimitive(): Promise; // Returns primitive
getObject(): Promise; // Returns object
hello(name: string): Promise; // Returns object
}
// Create client
const apiStub = newWebSocketRpcSession('wss://example.com/api');
// Primitives work correctly ✅
const primitive = await apiStub.getPrimitive();
// ^? Type is 'string' ✅
// Objects return 'any' ❌
const object = await apiStub.getObject();
// ^? Type is 'any' ❌
const helloResult = await apiStub.hello('world');
// ^? Type is 'any' ❌
```
## Expected Behavior
All method return types should be preserved, regardless of whether they're primitives or objects:
```typescript
const primitive = await apiStub.getPrimitive();
// ^? string ✅
const object = await apiStub.getObject();
// ^? Should be: ApiMessage
const helloResult = await apiStub.hello('world');
// ^? Should be: ApiMessage
```
## Actual Behavior
Only primitive return types are preserved. Object/interface return types become `any`:
```typescript
const apiStub: RpcStub = newWebSocketRpcSession('wss://example.com/api');
// ^? Correctly shows: RpcStub
const primitive = await apiStub.getPrimitive();
// ^? string ✅ Works!
const object = await apiStub.getObject();
// ^? any ❌ Should be ApiMessage
const helloResult = await apiStub.hello('world');
// ^? any ❌ Should be ApiMessage
// No type checking for objects
console.log(helloResult.anythingGoes); // No error
```
## Root Cause
The `RpcStub` type definition appears to handle primitives correctly but wraps object return types in complex proxy types (for promise pipelining support) that resolve to `any` instead of the original type.
## Workaround
Manually cast each result:
```typescript
const helloResult = await apiStub.hello('world') as ApiMessage;
// ^? Now correctly typed as: ApiMessage ✅
```
## Environment
- **capnweb version**: 0.2.0
- **TypeScript version**: 5.8.3
- **Node version**: 22.15.1
Contributor guide
Assessment
This issue has not been assessed yet.