Skip to main content
Search...

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 error

RouteReq

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'>
// => UserDto

Use 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'>
// => AuthSession

GetReq

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 error

DuckgenMessageDictionary

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 DuckgenMessageDictionaryByGroup

DuckgenI18n

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