-
Notifications
You must be signed in to change notification settings - Fork 76
fix: allow user-defined interfaces as Server Props #412
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| "partyserver": patch | ||
| --- | ||
|
|
||
| Allow user-defined interfaces as `Props`. | ||
|
|
||
| Interfaces do not get implicit index signatures in TypeScript, so the previous `Record<string, unknown>` bound rejected them with "Index signature for type 'string' is missing". `Props` is now bounded by `object` on `Server`, `getServerByName`, and `routePartykitRequest`, and the `T` constraints on the latter two are `Server<Env, object>` so subclasses declaring interface `Props` satisfy them too. Generic defaults stay `Record<string, unknown>`, so untyped usage still reads props values as `unknown`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| /** | ||
| * Type tests for Server props typing. Compile-time only — this file is | ||
| * typechecked but never executed (vitest only picks up `*.test.ts`). | ||
| * | ||
| * Interfaces do not get implicit index signatures in TypeScript, so a | ||
| * `Record<string, unknown>` bound rejects user-defined interfaces with | ||
| * "Index signature for type 'string' is missing". Props bounds must accept | ||
| * plain interfaces while still rejecting non-object props. | ||
| */ | ||
| import { Server, getServerByName, routePartykitRequest } from "../index"; | ||
|
|
||
| // A well-defined interface with NO index signature. | ||
| interface AuthProps { | ||
| userId: string; | ||
| permissions: string[]; | ||
| } | ||
|
|
||
| declare const authProps: AuthProps; | ||
| declare const env: Cloudflare.Env; | ||
| declare const request: Request; | ||
|
|
||
| // ============================================ | ||
| // POSITIVE TESTS - interface props must be accepted | ||
| // ============================================ | ||
|
|
||
| // Server must be instantiable with interface Props. | ||
| declare class AuthServer extends Server<Cloudflare.Env, AuthProps> {} | ||
| declare const serverNamespace: DurableObjectNamespace<AuthServer>; | ||
|
|
||
| // getServerByName must accept interface-typed props. | ||
| getServerByName(serverNamespace, "instance", { props: authProps }); | ||
|
|
||
| // onStart receives the interface type. | ||
| declare const authServer: AuthServer; | ||
| authServer.onStart(authProps); | ||
|
|
||
| // routePartykitRequest must accept interface-typed props. | ||
| routePartykitRequest(request, env, { props: authProps }); | ||
|
|
||
| // ============================================ | ||
| // NEGATIVE TESTS - non-object props stay rejected | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should have a negative test where you pass an object to |
||
| // ============================================ | ||
|
|
||
| // @ts-expect-error — a primitive is not a props bag | ||
| declare class BadServer extends Server<Cloudflare.Env, string> {} | ||
|
|
||
| getServerByName(serverNamespace, "instance", { | ||
| // @ts-expect-error — a primitive is not a props bag | ||
| props: "not-an-object" | ||
| }); | ||
|
|
||
| // Silence unused-declaration noise; this file only exists to typecheck. | ||
| export type {}; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this be
Server<Env, Props>to ensure that the props relate to the same type than the server type ?Or maybe inferring the default
Propstype from theServertype instead ?