Skip to content

Types Plugin ​

The @hedystia/types package provides standalone type generation for use with any web framework. This allows you to get Hedystia's powerful type inference with Express, Hono, Fastify, or any other framework.

Installation ​

bash
bun add @hedystia/types

Why Use Hedystia Types? ​

  • Type-safe clients — Generate a fully-typed client that mirrors your API
  • Framework-agnostic — Works with any framework
  • IDE autocomplete — Full IntelliSense support
  • Type inference — Automatic inference from your route definitions
  • No runtime overhead — Pure TypeScript definitions

Basic Usage ​

Define your routes as plain objects and generate types:

typescript
import { generateTypes } from '@hedystia/types'

const routes = [
  {
    method: 'GET',
    path: '/users/:id',
    params: { id: 'number' },
    response: { id: 'number', name: 'string', email: 'string' },
  },
  {
    method: 'POST',
    path: '/users',
    body: { name: 'string', email: 'string' },
    response: { id: 'number', name: 'string', email: 'string' },
  },
]

// Generate TypeScript definition file
await generateTypes(routes, './api.d.ts')

With Express ​

Set up Express routes and generate types:

typescript
// server.ts
import express from 'express'
import { generateTypes } from '@hedystia/types'

const routes = [
  {
    method: 'GET',
    path: '/api/posts/:id',
    params: { id: 'number' },
    response: { id: 'number', title: 'string', content: 'string' },
  },
]

await generateTypes(routes, './api.d.ts')

const app = express()

app.get('/api/posts/:id', (req, res) => {
  res.json({ id: 1, title: 'Hello', content: 'World' })
})

app.listen(3000)

Then use with the Hedystia client:

typescript
// client.ts
import { createClient } from '@hedystia/client'

type AppRoutes = [
  { method: 'GET'; path: '/api/posts/:id'; response: { id: number; title: string; content: string } }
]

const client = createClient<AppRoutes>('http://localhost:3000/api')
const { data } = await client.posts.id(1).get()

console.log(data?.title) // Fully typed!

With Hono ​

Use with Hono's lightweight runtime:

typescript
// server.ts
import { Hono } from 'hono'
import { generateTypes } from '@hedystia/types'

const routes = [
  {
    method: 'GET',
    path: '/users',
    response: [{ id: 'number'; name: 'string' }],
  },
  {
    method: 'POST',
    path: '/users',
    body: { name: 'string'; email: 'string' },
    response: { id: 'number'; name: 'string'; email: 'string' },
  },
]

await generateTypes(routes, './types.d.ts')

const app = new Hono()

app.get('/users', (c) => {
  return c.json([{ id: 1, name: 'Alice' }])
})

app.post('/users', async (c) => {
  const body = await c.req.json()
  return c.json({ id: 2, ...body })
})

export default app

Route Definition Format ​

typescript
interface RouteDefinition {
  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
  path: string
  params?: Record<string, string | number | boolean>
  query?: Record<string, string | number | boolean>
  body?: any
  headers?: Record<string, string>
  response: any
  data?: any
  error?: any
}

Type Inference ​

The generated types support full type inference:

typescript
type AppRoutes = [
  {
    method: 'GET'
    path: '/users/:id'
    params: { id: number }
    query: { include?: 'posts' | 'comments' }
    response: { id: number; name: string; email: string }
  },
]

const client = createClient<AppRoutes>('http://localhost:3000')

// Full type safety
const { data } = await client.users.id(1).get({
  query: { include: 'posts' }, // Autocomplete + validation
})

if (data) {
  console.log(data.id)    // ✓ Known
  console.log(data.name)  // ✓ Known
  // console.log(data.unknown) // ✗ TypeScript error
}

Advanced Patterns ​

Dynamic Route Generation ​

Generate types from your framework's routes:

typescript
import { generateTypes } from '@hedystia/types'
import { createServer } from './server'

const app = createServer()

// Extract routes from your framework and generate types
const routes = app.routes.map(route => ({
  method: route.method,
  path: route.path,
  response: route.responseType,
}))

await generateTypes(routes, './api.d.ts')

Build-Time Generation ​

Integrate type generation into your build process:

json
{
  "scripts": {
    "build:types": "bun build-types.ts",
    "build": "bun build:types && bun build server.ts",
    "dev": "bun build:types && bun --watch server.ts"
  }
}
typescript
// build-types.ts
import { generateTypes } from '@hedystia/types'
import routes from './routes'

await generateTypes(routes, './api.d.ts')
console.log('✓ Types generated')

Benefits Over REST Documentation ​

  • Compile-time safety — Catch typos and breaking changes at build time
  • Automatic updates — Types always match your server
  • No context switching — IDE autocomplete instead of API docs
  • Refactoring — Rename endpoints and find all usages
  • Team productivity — Frontend devs get instant feedback