createReactClient accepts a kinds option, documented as internal, marked with @internal, and effectively invisible to real apps. Its purpose is not for you. It exists so the adapters can be tested without a generated module.
The seam
export type ReactClientOptions = ClientOptions & {
/**
* @internal Override generated kinds. Prefer relying on codegen, adapters
* load `procedureKinds` from `@pyrpc/types` automatically.
*/
kinds?: ProcedureKindMap<ProceduresRecord>;
};A seam that is documented but discouraged. The JSDoc says it plainly: prefer codegen. The option exists as an escape hatch, and its placement in the options object (not a separate test-only constructor) keeps the public API surface small.
Why tests need it
The adapter imports procedureKinds from @pyrpc/types. In the published package, that module is the generated __pyrpc.ts, a file that does not exist in the adapter's own test environment, because codegen has not run there. Without the override, every test would have to either generate a module or hit the throwing placeholder.
createReactClient<{ greet: (...args: any[]) => Promise<string> }>({
baseUrl: "http://localhost:8000",
kinds: { greet: "query" },
})The test supplies its own kinds, mirroring what codegen would have emitted, and asserts the hook selection behavior (useQuery present, useMutation absent) independent of any codegen step. The override converts an integration dependency into a pure unit-test input.
What the tests actually assert
Because the kinds map is now an explicit input, the test suite can exercise every branch of the runtime selection logic:
- a query kind yields only
useQuery - a mutation kind yields only
useMutation - a missing kind yields both, the
undefinedfallback
Each case is a table row, not a bespoke test. The override makes the runtime behavior a pure function of (kind) and therefore exhaustively testable.
The design lesson
A test-only seam should be honest about being a seam. Hiding it behind mocks or magic globals would obscure what it is for. The @internal option is a contract with a caveat: you may inject kinds to test, but production relies on codegen, and the throwing placeholder enforces that distinction at runtime. Testability and safety, both intact.

pyRPC