Skip to content

Commit 17551f0

Browse files
authored
fix(openapi): preserve event iterator return type in JsonifiedClient (#1798)
v1 port of #1797. `JsonifiedClient` was losing an event iterator's return type: a contract with `eventIterator(z.number(), z.number())` produced an iterator with `TReturn = any` instead of the jsonified return type. `AsyncIteratorClass`'s `return(value?: any)` signature made TypeScript infer `TReturn` as `any` when matched against `AsyncIteratorObject<infer U, infer V>`, since inference works off actual method signatures rather than the `implements` clause. Fixes #1796 ## Fixes - `JsonifiedValue` now matches `AsyncIteratorClass` directly (its own case, ahead of the generic `AsyncIteratorObject` branch), so the return type inference is no longer poisoned. - `AsyncGenerator` and plain `AsyncIteratorObject` values now keep their own shape instead of being widened, matching the updated #1797. ## Testing - New type tests cover `JsonifiedValue` over `AsyncIteratorClass`/`AsyncGenerator`/`AsyncIteratorObject` and the end-to-end reproduction through `JsonifiedClient` (using v1's `eventIterator` + `ContractRouterClient`); three assertions fail before the fix and pass after. - Root `tsc -b`, `tsc --noEmit`, and eslint are clean.
1 parent 08a3cad commit 17551f0

2 files changed

Lines changed: 19 additions & 3 deletions

File tree

packages/openapi-client/src/types.test-d.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import type { Client, ORPCError } from '@orpc/client'
2+
import type { ContractRouterClient } from '@orpc/contract'
3+
import type { AsyncIteratorClass } from '@orpc/shared'
24
import type { JsonifiedClient, JsonifiedValue } from './types'
5+
import { eventIterator, oc, type } from '@orpc/contract'
36

47
describe('JsonifiedValue', () => {
58
it('flat', () => {
@@ -18,7 +21,9 @@ describe('JsonifiedValue', () => {
1821
expectTypeOf<JsonifiedValue<Set<number>>>().toEqualTypeOf<number[]>()
1922
expectTypeOf<JsonifiedValue<Array<number>>>().toEqualTypeOf<number[]>()
2023
expectTypeOf<JsonifiedValue<{ a: number, b: Date }>>().toEqualTypeOf<{ a: number, b: string }>()
21-
expectTypeOf<JsonifiedValue<AsyncGenerator<Date, Date>>>().toEqualTypeOf<AsyncIteratorObject<string, string>>()
24+
expectTypeOf<JsonifiedValue<AsyncIteratorClass<Date, Date>>>().toEqualTypeOf<AsyncIteratorClass<string, string>>()
25+
expectTypeOf<JsonifiedValue<AsyncGenerator<Date, Date>>>().toEqualTypeOf<AsyncGenerator<string, string>>()
26+
expectTypeOf<JsonifiedValue<AsyncIteratorObject<Date, Date>>>().toEqualTypeOf<AsyncIteratorObject<string, string>>()
2227

2328
expectTypeOf<JsonifiedValue<DateConstructor>>().toEqualTypeOf<unknown>()
2429
})
@@ -41,6 +46,14 @@ describe('JsonifiedClient', () => {
4146
>()
4247
})
4348

49+
it('preserves event iterator yield/return types', () => {
50+
const contract = oc.output(eventIterator(type<Date>(), type<Date>()))
51+
52+
expectTypeOf<
53+
Awaited<ReturnType<JsonifiedClient<ContractRouterClient<typeof contract>>>>
54+
>().toEqualTypeOf<AsyncIteratorClass<string, string>>()
55+
})
56+
4457
it('nested', () => {
4558
expectTypeOf<JsonifiedClient<{
4659
ping: Client<{ cache?: boolean }, { now: Date }, { b: Set<Date> }, Error | ORPCError<string, { a: Date }>>

packages/openapi-client/src/types.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Client, NestedClient, ORPCError } from '@orpc/client'
2+
import type { AsyncIteratorClass } from '@orpc/shared'
23

34
export type JsonifiedValue<T>
45
= T extends string ? T
@@ -16,8 +17,10 @@ export type JsonifiedValue<T>
1617
: T extends URL ? string
1718
: T extends Map<infer K, infer V> ? JsonifiedArray<[K, V][]>
1819
: T extends Set<infer U> ? JsonifiedArray<U[]>
19-
: T extends AsyncIteratorObject<infer U, infer V> ? AsyncIteratorObject<JsonifiedValue<U>, JsonifiedValue<V>>
20-
: unknown
20+
: T extends AsyncIteratorClass<infer U, infer V> ? AsyncIteratorClass<JsonifiedValue<U>, JsonifiedValue<V>>
21+
: T extends AsyncGenerator<infer U, infer V> ? AsyncGenerator<JsonifiedValue<U>, JsonifiedValue<V>>
22+
: T extends AsyncIteratorObject<infer U, infer V> ? AsyncIteratorObject<JsonifiedValue<U>, JsonifiedValue<V>>
23+
: unknown
2124

2225
export type JsonifiedArray<T extends Array<unknown>> = T extends readonly []
2326
? []

0 commit comments

Comments
 (0)