How to change identifier conventions
Change the naming convention for generated identifiers in a cloned generator (e.g., user → UserSchema, useGetUser → useUserQuery).
When to use this
You want the generated identifiers to match your team's naming conventions instead of the stock generator's defaults.
Prerequisites
- The generator cloned into your project (tutorial: cloning).
- Light understanding of identifiers and entity types.
Steps
Open gen-x/src/base.ts
The naming convention lives there, split across two config fields
on the toTsModelProjectionBase({...}) (or operation-equivalent)
call: toIdentifierName returns the name string, and
toIdentifierType declares whether the name is a variable
(a const declaration) or a type declaration.
Edit toIdentifierName
// gen-zod default
toIdentifierName: ({ refName }) => decapitalize(refName)
// → "user", "order", "pet"
// Your house style: PascalCase with suffix
toIdentifierName: ({ refName }) => `${refName}Schema`
// → "UserSchema", "OrderSchema", "PetSchema"For a type generator, have toIdentifierType return
{ type: 'type' } instead of { type: 'variable' }:
import type { TsIdentifierType } from '@skmtc/lang-typescript'
toIdentifierType: (): TsIdentifierType => ({ type: 'type' })
// → rendered as `export type User = ...` and imports as `import { type User }`The variable vs type choice determines:
- The declaration shape (
export constvsexport type) - The import shape under
verbatimModuleSyntax: true(import { X }vsimport { type X })
See identifier reference for the entity-type semantics.
Preserve uniqueness across operations
The (identifier.name, exportPath) pair is the cache key. If
two operations within your generator produce the same name in
the same file, the Driver's affirmDefinition detects the
mismatch (different generatorKey per operation) and throws
Registered definition mismatch. Re-inserting the same operation
is idempotent (same key → cache hit).
Make sure your naming function produces unique names per
operation/refName so the throw never fires. Helpers like
toEndpointName(operation) handle the OAS-spec quirks (missing
operationId, identical paths with different methods).
Rebundle and regenerate
skmtc bundle my-project
skmtc generate my-projectVerification
Open an generated file and check the declarations:
cat src/generated/Pet.generated.ts | head -3
# export const PetSchema = z.object({...}) ← new namingCross-generator references (e.g., a form generator importing the
Zod schema) follow the new name automatically — they discover
it via insertModel(...).toName(), not by hardcoded reference.
Troubleshooting
- Imports break under
verbatimModuleSyntax— A type declaration whosetoIdentifierTypereturns{ type: 'variable' }(or vice versa) causes TS errors. Audit which generators produce values vs types and make sure each is right. - Same identifier name across operations — naming function
isn't unique enough. Common bug: derivation from
operation.summaryrather thanoperationId(summaries are free text and not required to be unique).
Related
- API: Identifier — including the entity-type discussion
- How to change export paths — the sibling task
- How idempotency works — why uniqueness matters