generated types
Complete reference for every type exported by Duck Gen, with usage examples for API routes and message registries.
Overview
When you run duck-gen, it generates .d.ts files that export types describing your
API routes and message registries. This page documents every exported type with
examples showing how to use each one.
Loading diagram...
Import generated types from the framework entrypoint:
import type {
// API route types
ApiRoutes,
RoutePath,
RouteReq,
RouteRes,
RouteMethod,
RouteMethods,
PathsByMethod,
DuckFetcher,
DuckClient,
GetBody,
GetQuery,
GetParams,
GetHeaders,
GetRes,
GetReq,
// Message types
DuckgenMessageSources,
DuckgenMessageGroup,
DuckgenMessageKey,
DuckgenMessageDictionary,
DuckgenMessageDictionaryByGroup,
DuckGenI18nMessages,
DuckgenI18n,
DuckgenI18nByGroup,
DuckgenScopedI18nByGroup,
} from '@gentleduck/gen/nestjs'API route types
These types are generated from your NestJS controllers.
ApiRoutes
The main route map. Each key is a route path, and the value is an object describing the method, request shape, and response type.
// The generated interface looks like:
interface ApiRoutes {
'/api/auth/signin': {
body: SigninDto
query: never
params: never
headers: never
res: AuthSession
method: 'POST'
}
'/api/users/:id': {
body: never
query: never
params: { id: string }
headers: never
res: UserDto
method: 'GET'
}
}Use ApiRoutes as a generic parameter when creating a Duck Query client:
import { createDuckQueryClient } from '@gentleduck/query'
import type { ApiRoutes } from '@gentleduck/gen/nestjs'
const client = createDuckQueryClient<ApiRoutes>({
baseURL: 'http://localhost:3000',
})RoutePath
A union of all route path strings.
type RoutePath = '/api/auth/signin' | '/api/users/:id' | '/api/users'Use it to constrain a variable or parameter to valid route paths:
function logRoute(path: RoutePath) {
console.log(`Calling ${path}`)
}
logRoute('/api/auth/signin') // ok
logRoute('/api/unknown') // error: type errorRouteReq
The request shape for a given route path. Returns an object with body, query, params,
and headers fields, but only the fields that are not never for that route.
type SigninReq = RouteReq<'/api/auth/signin'>
// => { body: SigninDto }
type UserReq = RouteReq<'/api/users/:id'>
// => { params: { id: string } }
type SearchReq = RouteReq<'/api/users'>
// => { query: PaginationDto }This is the type you use most often when building forms or request objects:
function buildSigninPayload(): RouteReq<'/api/auth/signin'> {
return {
body: {
username: 'duck',
password: '123456',
},
}
}RouteRes
The response type for a given route path.
type SigninRes = RouteRes<'/api/auth/signin'>
// => AuthSession
type UserRes = RouteRes<'/api/users/:id'>
// => UserDtoUse it to type your response handlers:
function handleSignin(response: RouteRes<'/api/auth/signin'>) {
console.log('Signed in as', response.username)
}RouteMethod
The HTTP method for a given route path.
type SigninMethod = RouteMethod<'/api/auth/signin'>
// => 'POST'
type UserMethod = RouteMethod<'/api/users/:id'>
// => 'GET'RouteMethods
A union of all HTTP methods used across all routes.
type AllMethods = RouteMethods
// => 'GET' | 'POST' | 'PUT' | 'DELETE' | ...PathsByMethod
Filters route paths by a specific HTTP method. Returns only paths that use the given method.
type GetPaths = PathsByMethod<'GET'>
// => '/api/users/:id' | '/api/users'
type PostPaths = PathsByMethod<'POST'>
// => '/api/auth/signin' | '/api/users'This is useful for building method-specific utilities:
async function fetchAll<P extends PathsByMethod<'GET'>>(
client: DuckQueryClient<ApiRoutes>,
path: P,
) {
return client.get(path)
}GetBody, GetQuery, GetParams, GetHeaders
Individual type extractors for each request component:
type SigninBody = GetBody<'/api/auth/signin'>
// => SigninDto
type UserParams = GetParams<'/api/users/:id'>
// => { id: string }
type SearchQuery = GetQuery<'/api/users'>
// => PaginationDto
type AuthHeaders = GetHeaders<'/api/me'>
// => { authorization: string }GetRes
An alias for RouteRes. Use whichever reads better:
type SigninResponse = GetRes<'/api/auth/signin'>
// => AuthSessionGetReq
An alias for RouteReq:
type SigninRequest = GetReq<'/api/auth/signin'>
// => { body: SigninDto }DuckFetcher
A typed fetcher function signature for a route path:
type Fetcher = DuckFetcher<'/api/auth/signin'>
// => (req: { body: SigninDto }) => Promise<AuthSession>DuckClient
A typed client helper with request and byMethod methods:
type Client = DuckClient
// => { request: ...; byMethod: ... }Message types
These types are generated from @duckgen tagged constants.
DuckgenMessageSources
Maps group keys to their source types. This is the raw registry:
type DuckgenMessageSources = {
auth: typeof AuthMessages // from @duckgen messages auth
payments: typeof PaymentMessages // from @duckgen messages payments
}DuckgenMessageGroup
A union of all group keys:
type DuckgenMessageGroup = 'auth' | 'payments'Use it to build group-aware functions:
function getTranslations(group: DuckgenMessageGroup, lang: string) {
return i18n[lang].server[group]
}DuckgenMessageKey
A union of message keys, optionally scoped to a group:
// All keys across all groups
type AllKeys = DuckgenMessageKey
// => 'AUTH_SIGNIN_SUCCESS' | 'AUTH_SIGNIN_FAILED' | 'PAYMENT_SUCCESS' | ...
// Keys for a specific group
type AuthKeys = DuckgenMessageKey<'auth'>
// => 'AUTH_SIGNIN_SUCCESS' | 'AUTH_SIGNIN_FAILED' | ...Use it for type-safe error handling:
function showError(key: DuckgenMessageKey<'auth'>, lang: 'en' | 'ar') {
const message = i18n[lang].server.AuthMessages[key]
toast.error(message)
}
showError('AUTH_SIGNIN_FAILED', 'en') // ok
showError('UNKNOWN_KEY', 'en') // error: type errorDuckgenMessageDictionary
A record mapping message keys to string values for a group. This is the shape of a single translation file:
type AuthDict = DuckgenMessageDictionary<'auth'>
// => {
// AUTH_SIGNIN_SUCCESS: string
// AUTH_SIGNIN_FAILED: string
// AUTH_USERNAME_INVALID: string
// AUTH_PASSWORD_INVALID: string
// }Use it to type your translation objects:
const authEn: DuckgenMessageDictionary<'auth'> = {
AUTH_SIGNIN_SUCCESS: 'Signed in successfully',
AUTH_SIGNIN_FAILED: 'Sign in failed',
AUTH_USERNAME_INVALID: 'Invalid username',
AUTH_PASSWORD_INVALID: 'Invalid password',
}TypeScript will error if you miss a key or add an unknown key.
DuckgenMessageDictionaryByGroup
All groups mapped to their dictionaries in one object:
type AllDicts = DuckgenMessageDictionaryByGroup
// => {
// auth: { AUTH_SIGNIN_SUCCESS: string; ... }
// payments: { PAYMENT_SUCCESS: string; ... }
// }DuckGenI18nMessages
An alias of DuckgenMessageDictionaryByGroup. Use whichever name reads better:
type Messages = DuckGenI18nMessages
// Same as DuckgenMessageDictionaryByGroupDuckgenI18n
Maps language codes to message dictionaries. Accepts language union and optional group:
type AuthI18n = DuckgenI18n<'en' | 'ar', 'auth'>
// => {
// en: { AUTH_SIGNIN_SUCCESS: string; ... }
// ar: { AUTH_SIGNIN_SUCCESS: string; ... }
// }DuckgenI18nByGroup
Maps language codes to all group dictionaries:
type FullI18n = DuckgenI18nByGroup<'en' | 'ar'>
// => {
// en: { auth: { ... }; payments: { ... } }
// ar: { auth: { ... }; payments: { ... } }
// }DuckgenScopedI18nByGroup
The most commonly used i18n type. Wraps all groups under a server scope, making it
easy to separate server-generated messages from client-only translations:
type ScopedI18n = DuckgenScopedI18nByGroup<'en' | 'ar', DuckGenI18nMessages>
// => {
// en: {
// server: {
// AuthMessages: { AUTH_SIGNIN_SUCCESS: string; ... }
// PaymentMessages: { PAYMENT_SUCCESS: string; ... }
// }
// }
// ar: {
// server: {
// AuthMessages: { AUTH_SIGNIN_SUCCESS: string; ... }
// PaymentMessages: { PAYMENT_SUCCESS: string; ... }
// }
// }
// }Full usage example:
import type { DuckgenScopedI18nByGroup, DuckGenI18nMessages } from '@gentleduck/gen/nestjs'
type Lang = 'en' | 'ar'
type I18n = DuckgenScopedI18nByGroup<Lang, DuckGenI18nMessages>
const i18n: I18n = {
en: {
server: {
AuthMessages: {
AUTH_SIGNIN_SUCCESS: 'Signed in successfully',
AUTH_SIGNIN_FAILED: 'Sign in failed',
// ... TypeScript enforces all keys are present
},
PaymentMessages: {
PAYMENT_SUCCESS: 'Payment processed',
PAYMENT_DECLINED: 'Payment declined',
},
},
},
ar: {
server: {
AuthMessages: {
AUTH_SIGNIN_SUCCESS: 'تم تسجيل الدخول بنجاح',
AUTH_SIGNIN_FAILED: 'فشل تسجيل الدخول',
},
PaymentMessages: {
PAYMENT_SUCCESS: 'تم الدفع بنجاح',
PAYMENT_DECLINED: 'تم رفض الدفع',
},
},
},
}Next steps
- API Routes guide: how routes are scanned and generated.
- Messages guide: how message tags work.
- Duck Query: use these types with a type-safe HTTP client.
- Templates: complete working example.