Skip to content

feat: generate a resource that has type parameters - #77

Closed
moetemp wants to merge 1 commit into
review/p3-basefrom
review/p3-generic
Closed

moetemp wants to merge 1 commit into
review/p3-basefrom
review/p3-generic

Conversation

@moetemp

@moetemp moetemp commented Oct 28, 2026

Copy link
Copy Markdown
Owner

What changed?

This PR lets a resource declare its type parameters, in Python, TypeScript and .NET.

A resource names each type parameter alias that it uses with @nexus.type-parameter "<alias>", in order. The alias can come from another interface through use. The resource class is then generic, and it keeps a runtime type for each parameter.

  • An operation that returns the resource takes one runtime type for each parameter, since its request can't give one. The create of the stream sample is create_stream(Turn, stream_id=...) in Python, and it returns a Stream[Turn].
  • An operation that a method binds takes a runtime type for each parameter that only its output uses. The read takes one, and the append takes none, since its request carries the values.
  • The data converter decodes the generic values of a response with the runtime types. Python passes ReadRecordsResponse[body_type] as the output type. TypeScript converts the response with the model's create<Model>TransferTypeConverter factory and the handle's TypeInfo. .NET calls the generic operation with the class's TBody.
  • Go and Java refuse a generic resource.

nexgen also refuses a resource that uses a parameter that it doesn't declare (also through a proto-backed record), a declared parameter that the resource doesn't use, and a parameter of a bound operation that the resource doesn't declare. A generic resource can't be the result of an operation with no @nexus.proto message, or a field of a record, since neither carries the type arguments.

The stream samples take the parameter body-t on the bodies of append-record and stream-data, and the Stream and the writer declare it. Brook's WIT takes the same directives later.

The TypeScript resource methods now branch on a string parameter only when the parameter is a function reference. Before, a bound operation with a generic request made every optional string parameter branch.

It is for review here before it goes upstream. It sits on the upstream stack temporalio#308, temporalio#310, temporalio#311, temporalio#297, temporalio#296, temporalio#303, temporalio#304, temporalio#309, temporalio#318, temporalio#319, temporalio#320, temporalio#321, temporalio#322, temporalio#323, temporalio#324, temporalio#325, whose head is review/p3-base.

Why?

The Stream API of the proposal is generic in its value type, as in Stream[Turn]. The generated Stream class is that API, so the body of a read must decode as the handle's type, not as a raw payload. A resource couldn't use a type parameter at all before this PR.

How did you test it?

Python tests decode a read through the System Nexus converter with the handle's body type, and check Stream[Turn] and ReadRecordsResponse[Turn] with assert_type under basedpyright. A TypeScript test checks that the started read decodes a body with the handle's TypeInfo, and it checks the types with expectTypeOf. A .NET test round trips a data item as ReadRecordsResponse<Turn>, and a compile check reads a Stream<Turn>. Unit tests cover the runtime types of each stream operation, and a writer parameter that use brings in. Rejection fixtures cover each refusal.
cargo validate passes.

A resource with `@nexus.type-parameter "<alias>"` is generic in Python, TypeScript and .NET. Its
operations take a runtime type where the request can't give one, so a response decodes its generic
values.
@moetemp

moetemp commented Oct 28, 2026

Copy link
Copy Markdown
Owner Author

Duplicate of #78, which has the same commit.

@moetemp moetemp closed this Oct 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant