Naming Conventions
Typeweaver names are not just cosmetic. Resource names, operationId values, and response names all shape the generated clients, validators, request types, and response types you work with later.
Choose them like public API surface for your own codebase.
The short recommendation
Upstream guidance prefers:
- singular camelCase resource names such as
todoorauthSession - camelCase
operationIdvalues such asgetTodoorcreateTodo - clear PascalCase response names such as
GetTodoSuccessorTodoNotFoundError
That is the official preference.
These docs still use PascalCase examples for many operations because generated class names such as GetTodoRequestCommand, TodoClient, and GetTodoResponseValidator are also PascalCase, and the current examples are easier to scan that way.
The important compatibility point is simple: camelCase is preferred, PascalCase is fully supported, and snake_case / kebab-case are rejected.
operationId naming
Preferred
Official guidance prefers camelCase:
operationId: "getTodo"
operationId: "createTodo"
Also supported
PascalCase is fully supported and appears throughout current examples and tests:
operationId: "GetTodo"
operationId: "CreateTodo"
These docs use PascalCase in many examples for consistency with generated class names and surrounding documentation.
Not supported
These formats are not supported:
operationId: "get_todo"
operationId: "get-todo"
Resource naming
Preferred
Prefer a singular camelCase resource key in defineSpec(...):
resources: {
todo: {
operations: [GetTodoDefinition],
},
}
Good examples:
todouserauthSession
Also supported
The current project also supports:
- PascalCase resource names such as
Todo - plural resource names such as
todos
Those work, but singular camelCase tends to produce the cleanest long-term output.
Not supported
These are not supported for resource names:
todo_itemtodo-item
Response naming
Response names should be explicit and descriptive because they become the response.type discriminator and generated type/factory names.
Examples:
GetTodoSuccessValidationErrorTodoNotFoundError
Global uniqueness rule
Response names must be globally unique across the whole spec.
This is valid:
defineResponse({ name: "ValidationError", ... })
defineResponse({ name: "TodoNotFoundError", ... })
This is not:
// reused for a different response shape somewhere else
defineResponse({ name: "ValidationError", ... })
If two different responses share the same name, generation fails.
How names show up in generated output
| Spec name | Where it appears |
|---|---|
| resource name | generated folders and resource-level classes such as TodoClient, TodoRouter, TodoHono, TodoHttpApiRoutes |
operationId | request/response validators, request commands, handler method names, operation files |
| response name | response.type, generated response types, and create<ResponseName>Response(...) factory names |
That is why naming cleanup later can create noisy diffs across generated code.
Choosing between camelCase and PascalCase for operationId
Use this rule and move on:
- starting a new codebase today: choose camelCase
- matching an existing Typeweaver codebase that already uses PascalCase heavily: staying consistent is fine
Consistency inside one spec matters more than chasing style purity across old and new files.
Practical pitfalls
Avoid these common mistakes:
- changing names casually after clients or handlers already depend on them
- mixing
getTodo,CreateTodo, andlist_todosstyles in one spec - using vague response names like
SuccessorError - reusing the same response name for different shapes