generated types
Complete reference for every type exported by Duck Gen, with usage examples for API routes and message registries.
Overview
duck-gen emits .d.ts files that export types for API routes and message registries.
This page lists every exported type with a usage example.
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'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
Generated from NestJS controllers.
ApiRoutes
The main route map. Each key is a route path; the value describes 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'
}
}// 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'
}
}Pass ApiRoutes as the generic 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',
})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'type RoutePath = '/api/auth/signin' | '/api/users/:id' | '/api/users'Use it to restrict 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 errorfunction logRoute(path: RoutePath) {
console.log(`Calling ${path}`)
}
logRoute('/api/auth/signin') // ok
logRoute('/api/unknown') // error: type errorRouteReq
The request shape for a route. An object with body, query, params, and headers,
filtered to 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 }type SigninReq = RouteReq<'/api/auth/signin'>
// => { body: SigninDto }
type UserReq = RouteReq<'/api/users/:id'>
// => { params: { id: string } }
type SearchReq = RouteReq<'/api/users'>
// => { query: PaginationDto }The type you'll reach for most often when building request payloads:
function buildSigninPayload(): RouteReq<'/api/auth/signin'> {
return {
body: {
username: 'duck',
password: '123456',
},
}
}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'>
// => UserDtotype SigninRes = RouteRes<'/api/auth/signin'>
// => AuthSession
type UserRes = RouteRes<'/api/users/:id'>
// => UserDtoUse it to type response handlers:
function handleSignin(response: RouteRes<'/api/auth/signin'>) {
console.log('Signed in as', response.username)
}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'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' | ...type AllMethods = RouteMethods
// => 'GET' | 'POST' | 'PUT' | 'DELETE' | ...PathsByMethod
Filters route paths by HTTP method — returns only paths using that method.
type GetPaths = PathsByMethod<'GET'>
// => '/api/users/:id' | '/api/users'
type PostPaths = PathsByMethod<'POST'>
// => '/api/auth/signin' | '/api/users'type GetPaths = PathsByMethod<'GET'>
// => '/api/users/:id' | '/api/users'
type PostPaths = PathsByMethod<'POST'>
// => '/api/auth/signin' | '/api/users'Useful for method-specific helpers:
async function fetchAll<P extends PathsByMethod<'GET'>>(
client: DuckQueryClient<ApiRoutes>,
path: P,
) {
return client.get(path)
}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 }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
Alias for RouteRes. Pick whichever name reads better:
type SigninResponse = GetRes<'/api/auth/signin'>
// => AuthSessiontype SigninResponse = GetRes<'/api/auth/signin'>
// => AuthSessionGetReq
Alias for RouteReq:
type SigninRequest = GetReq<'/api/auth/signin'>
// => { body: SigninDto }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>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: ... }type Client = DuckClient
// => { request: ...; byMethod: ... }Message types
Generated from @duckgen tagged constants.
DuckgenMessageSources
Maps group keys to their source types — the raw registry:
type DuckgenMessageSources = {
auth: typeof AuthMessages // from @duckgen messages auth
payments: typeof PaymentMessages // from @duckgen messages payments
}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'type DuckgenMessageGroup = 'auth' | 'payments'Use it for group-aware functions:
function getTranslations(group: DuckgenMessageGroup, lang: string) {
return i18n[lang].server[group]
}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' | ...// 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' | ...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 errorfunction 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 — the shape of one translation file:
type AuthDict = DuckgenMessageDictionary<'auth'>
// => {
// AUTH_SIGNIN_SUCCESS: string
// AUTH_SIGNIN_FAILED: string
// AUTH_USERNAME_INVALID: string
// AUTH_PASSWORD_INVALID: string
// }type AuthDict = DuckgenMessageDictionary<'auth'>
// => {
// AUTH_SIGNIN_SUCCESS: string
// AUTH_SIGNIN_FAILED: string
// AUTH_USERNAME_INVALID: string
// AUTH_PASSWORD_INVALID: string
// }Use it to type 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',
}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',
}A missing key or an unknown key triggers a TypeScript error.
DuckgenMessageDictionaryByGroup
All groups mapped to their dictionaries in one object:
type AllDicts = DuckgenMessageDictionaryByGroup
// => {
// auth: { AUTH_SIGNIN_SUCCESS: string; ... }
// payments: { PAYMENT_SUCCESS: string; ... }
// }type AllDicts = DuckgenMessageDictionaryByGroup
// => {
// auth: { AUTH_SIGNIN_SUCCESS: string; ... }
// payments: { PAYMENT_SUCCESS: string; ... }
// }DuckGenI18nMessages
Alias for DuckgenMessageDictionaryByGroup. Pick whichever name reads better:
type Messages = DuckGenI18nMessages
// Same as DuckgenMessageDictionaryByGrouptype Messages = DuckGenI18nMessages
// Same as DuckgenMessageDictionaryByGroupDuckgenI18n
Maps language codes to message dictionaries. Takes a language union and an optional group:
type AuthI18n = DuckgenI18n<'en' | 'ar', 'auth'>
// => {
// en: { AUTH_SIGNIN_SUCCESS: string; ... }
// ar: { AUTH_SIGNIN_SUCCESS: string; ... }
// }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: { ... } }
// }type FullI18n = DuckgenI18nByGroup<'en' | 'ar'>
// => {
// en: { auth: { ... }; payments: { ... } }
// ar: { auth: { ... }; payments: { ... } }
// }DuckgenScopedI18nByGroup
The most common i18n type. Wraps all groups under a server scope, separating
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; ... }
// }
// }
// }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: 'تم رفض الدفع',
},
},
},
}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.