Chapter 4: Generating Types
Run Duck Gen for the first time and understand the generated output files.
Run the generator
With your controller from the previous chapter in place, run Duck Gen:
bun run generateYou should see:
Config loaded
Processing doneExplore the output
Duck Gen creates two main output files. Let us look at each one.
Route types
Open generated/duck-gen-api-routes.d.ts. You will see something like this:
export interface DuckgenApiRoutes {
'/api/users': {
GET: {
body: never
query: {
page?: number
limit?: number
}
params: never
headers: never
response: {
data: {
id: string
name: string
email: string
createdAt: string
}[]
message: 'USER_CREATED' | 'USER_UPDATED' | 'USER_DELETED' | 'USER_FOUND' | 'USERS_LISTED'
success: boolean
}
}
POST: {
body: {
name: string
email: string
password: string
}
query: never
params: never
headers: never
response: {
data: {
id: string
name: string
email: string
createdAt: string
}
message: 'USER_CREATED' | 'USER_UPDATED' | 'USER_DELETED' | 'USER_FOUND' | 'USERS_LISTED'
success: boolean
}
}
}
'/api/users/:id': {
GET: {
body: never
query: never
params: {
id: string
}
headers: never
response: {
data: {
id: string
name: string
email: string
createdAt: string
}
message: 'USER_CREATED' | 'USER_UPDATED' | 'USER_DELETED' | 'USER_FOUND' | 'USERS_LISTED'
success: boolean
}
}
// PUT and DELETE entries follow the same pattern...
}
}Key observations:
- Every route path is a key in the
DuckgenApiRoutesinterface. - Each path contains its supported HTTP methods.
- Each method has fully resolved
body,query,params,headers, andresponsetypes. - Unused fields are typed as
never, meaning TypeScript will prevent you from sending data that the route does not accept. - Generics like
ApiResponse<UserDto, UserMessage>are fully expanded.
Message types
Open generated/duck-gen-messages.d.ts. If you have not added @duckgen tags yet (we
will do that in Chapter 6), this file will be minimal or contain empty registries.
Barrel exports
Duck Gen also creates index.d.ts barrel files that re-export everything:
export * from './duck-gen-api-routes'
export * from './duck-gen-messages'The package output
In addition to your ./generated folder, Duck Gen writes the same files inside
node_modules/@gentleduck/gen/generated/nestjs/. This is the primary import path:
import type { ApiRoutes, RouteReq, RouteRes } from '@gentleduck/gen/nestjs'Understanding utility types
Duck Gen ships several utility types that make working with the route map easier.
You do not need to read the raw DuckgenApiRoutes interface directly.
ApiRoutes
The full route map type. Useful when you need to iterate over all routes or build generic utilities:
import type { ApiRoutes } from '@gentleduck/gen/nestjs'
// ApiRoutes is the DuckgenApiRoutes interface
type AllPaths = keyof ApiRoutes // '/api/users' | '/api/users/:id'RouteReq<Path, Method?>
Extracts the request shape for a specific route and method. Returns only the non-never
fields:
import type { RouteReq } from '@gentleduck/gen/nestjs'
type CreateUserReq = RouteReq<'/api/users', 'POST'>
// { body: { name: string; email: string; password: string } }
type ListUsersReq = RouteReq<'/api/users', 'GET'>
// { query: { page?: number; limit?: number } }
type GetUserReq = RouteReq<'/api/users/:id', 'GET'>
// { params: { id: string } }RouteRes<Path, Method?>
Extracts the response type:
import type { RouteRes } from '@gentleduck/gen/nestjs'
type CreateUserRes = RouteRes<'/api/users', 'POST'>
// { data: UserDto; message: UserMessage; success: boolean }If you rename a DTO field on the server and re-run duck-gen, any client code that
uses the old field name will show a TypeScript error. This is exactly what you want.
The type system catches the mismatch before your users do.
Regeneration workflow
Every time you change your server code, run duck-gen again:
# One-time generation
bun run generate
# Or watch mode for continuous updates during development
bun run generate:watchThe generated files are deterministic. Running Duck Gen twice with the same source code produces identical output. This makes it safe to run in CI/CD pipelines.