Skip to content

fix: allow user-defined interfaces as Server Props#412

Open
mattzcarey wants to merge 1 commit into
mainfrom
fix/agent-props-interface-types
Open

fix: allow user-defined interfaces as Server Props#412
mattzcarey wants to merge 1 commit into
mainfrom
fix/agent-props-interface-types

Conversation

@mattzcarey

Copy link
Copy Markdown

Summary

The Props generic on Server, getServerByName, and routePartykitRequest was bounded by Record<string, unknown>. Interfaces do not get implicit index signatures in TypeScript, so a well-typed interface fails that bound with:

Type 'MyProps' is not assignable to type 'Record<string, unknown>'.
  Index signature for type 'string' is missing in type 'MyProps'.

This surfaced downstream as cloudflare/agents#1886 (getAgentByName(ns, name, { props: config }) rejecting interface-typed props) — the agents SDK inherits these bounds through Server and getServerByName, so the root fix belongs here.

Fix — object bounds, no any, no casts

  • Props extends object = Record<string, unknown> on Server, getServerByName, and routePartykitRequest. Interfaces satisfy object natively; defaults stay Record<string, unknown> so untyped usage still reads props values as unknown. Props is only ever treated as an opaque JSON bag at runtime (encodeProps/decodeProps already type it unknown), so nothing behavioral changes.
  • T extends Server<Env, object> = Server<Env> on getServerByName/routePartykitRequest. Two things forced this: the #_props private field carries Props covariantly, so a subclass declaring interface Props failed the old Server<Env> constraint (whose Props silently pinned to the Record default); and the DO stub's setName parameter resolves from the constraint, so options.props wouldn't flow without it. The default stays Server<Env>, keeping the return type for untyped callers identical.

Repro / regression tests

New compile-time test packages/partyserver/src/tests/props.test-d.ts — typechecked by check:type but never executed (vitest only picks up *.test.ts). Written first and confirmed red on main with errors matching the report:

  • Server declared with interface Props
  • getServerByName / routePartykitRequest called with interface-typed props
  • onStart receiving the interface type
  • negative pins: primitives are still rejected as Props

Verification

npm run build && npm run check fully green (sherif, oxfmt, oxlint, all 42 typecheck projects, all workspace test suites).

Once this ships, cloudflare/agents can bump partyserver and loosen its own Props bounds without any bridging (supersedes the approach in cloudflare/agents#1906, closed in favor of fixing it here).

Interfaces do not get implicit index signatures in TypeScript, so the
Record<string, unknown> bound on Props rejected them with 'Index
signature for type string is missing' (surfaced downstream as
cloudflare/agents#1886).

Bound Props by 'object' on Server, getServerByName, and
routePartykitRequest. The T constraints on the latter two become
Server<Env, object>: the #_props private field carries Props
covariantly, so a subclass declaring interface Props failed the old
Server<Env> constraint, and the DO stub's setName param resolved to the
constraint's Record type. Defaults stay Record<string, unknown> so
untyped usage still reads props values as unknown.
@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: de5bc27

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
partyserver Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 9, 2026

Copy link
Copy Markdown

Open in StackBlitz

hono-party

npm i https://pkg.pr.new/cloudflare/partykit/hono-party@412

partyfn

npm i https://pkg.pr.new/cloudflare/partykit/partyfn@412

partyserver

npm i https://pkg.pr.new/cloudflare/partykit/partyserver@412

partysocket

npm i https://pkg.pr.new/cloudflare/partykit/partysocket@412

partysub

npm i https://pkg.pr.new/cloudflare/partykit/partysub@412

partysync

npm i https://pkg.pr.new/cloudflare/partykit/partysync@412

partytracks

npm i https://pkg.pr.new/cloudflare/partykit/partytracks@412

partywhen

npm i https://pkg.pr.new/cloudflare/partykit/partywhen@412

y-partyserver

npm i https://pkg.pr.new/cloudflare/partykit/y-partyserver@412

commit: de5bc27

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