Documentation Index Fetch the complete documentation index at: https://mintlify.com/honojs/hono/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Hono is built with TypeScript and provides excellent type safety out of the box. With Hono’s type system, you get full autocomplete and type checking for routes, middleware, validation, and more.
Environment Types
Define types for your application’s environment variables and context variables using the Env type.
Bindings
Bindings are environment-specific values (like environment variables on Cloudflare Workers):
import { Hono } from 'hono'
type Bindings = {
TOKEN : string
KV : KVNamespace
DB : D1Database
}
const app = new Hono <{ Bindings : Bindings }>()
app . get ( '/' , ( c ) => {
const token = c . env . TOKEN // typed as string
const kv = c . env . KV // typed as KVNamespace
return c . text ( 'Hello!' )
})
Variables
Variables are values you set and get using c.set() and c.get():
type Variables = {
user : {
id : string
name : string
role : 'admin' | 'user'
}
requestId : string
}
const app = new Hono <{ Variables : Variables }>()
app . use ( '*' , async ( c , next ) => {
c . set ( 'requestId' , crypto . randomUUID ())
await next ()
})
app . get ( '/profile' , ( c ) => {
const user = c . get ( 'user' ) // fully typed!
const requestId = c . get ( 'requestId' ) // typed as string
return c . json ({ user , requestId })
})
Combined Environment
type Env = {
Bindings : {
DATABASE_URL : string
API_KEY : string
}
Variables : {
user : User
session : Session
}
}
const app = new Hono < Env >()
Type-Safe Routing
Hono infers types from your route patterns:
app . get ( '/posts/:id' , ( c ) => {
const id = c . req . param ( 'id' ) // typed as string
return c . json ({ id })
})
app . get ( '/search/:category/:tag' , ( c ) => {
const { category , tag } = c . req . param ()
// both typed as string
return c . json ({ category , tag })
})
Validation Types
Get full type safety with validation:
import { validator } from 'hono/validator'
app . post (
'/users' ,
validator ( 'json' , ( value , c ) => {
const parsed = value as {
name : string
email : string
age : number
}
// validation logic
if ( ! parsed . name ) {
return c . text ( 'Invalid!' , 400 )
}
return parsed
}),
( c ) => {
const data = c . req . valid ( 'json' )
// data is typed as { name: string, email: string, age: number }
return c . json ({ created: true })
}
)
Using Zod for Validation
Zod provides even better type inference:
import { z } from 'zod'
import { zValidator } from '@hono/zod-validator'
const userSchema = z . object ({
name: z . string (). min ( 1 ),
email: z . string (). email (),
age: z . number (). int (). min ( 18 ),
role: z . enum ([ 'admin' , 'user' ]). default ( 'user' ),
})
type User = z . infer < typeof userSchema >
app . post (
'/users' ,
zValidator ( 'json' , userSchema ),
( c ) => {
const user = c . req . valid ( 'json' )
// user is fully typed with all Zod transformations!
return c . json ({ user })
}
)
Generic Types
Understand Hono’s key generic types:
Env
The environment type containing Bindings and Variables:
export type Env = {
Bindings ?: Bindings
Variables ?: Variables
}
Handler
The handler function type:
export type Handler <
E extends Env = any ,
P extends string = any ,
I extends Input = BlankInput ,
R extends HandlerResponse < any > = any ,
> = ( c : Context < E , P , I >, next : Next ) => R
MiddlewareHandler
The middleware function type:
export type MiddlewareHandler <
E extends Env = any ,
P extends string = string ,
I extends Input = {},
R extends HandlerResponse < any > = Response ,
> = ( c : Context < E , P , I >, next : Next ) => Promise < R | void >
Custom Middleware Types
Create type-safe custom middleware:
import { MiddlewareHandler } from 'hono/types'
type MyEnv = {
Variables : {
userId : string
}
}
const authMiddleware : MiddlewareHandler < MyEnv > = async ( c , next ) => {
const token = c . req . header ( 'Authorization' )
if ( ! token ) {
return c . text ( 'Unauthorized' , 401 )
}
const userId = await verifyToken ( token )
c . set ( 'userId' , userId ) // type-checked!
await next ()
}
app . use ( '*' , authMiddleware )
app . get ( '/me' , ( c ) => {
const userId = c . get ( 'userId' ) // typed as string
return c . json ({ userId })
})
Response Types
Type your JSON responses:
type Post = {
id : string
title : string
body : string
createdAt : Date
}
app . get ( '/posts/:id' , async ( c ) => {
const post = await db . getPost ( c . req . param ( 'id' ))
return c . json < Post >( post ) // Response typed as Post
})
Context Types
Import and use Context types in your code:
import { Context } from 'hono'
type Env = {
Variables : {
user : User
}
}
async function getCurrentUser ( c : Context < Env >) : Promise < User > {
return c . get ( 'user' )
}
app . get ( '/profile' , async ( c ) => {
const user = await getCurrentUser ( c )
return c . json ( user )
})
Type Utilities
Hono provides type utilities for common patterns:
import type {
Input ,
BlankInput ,
BlankSchema ,
BlankEnv ,
} from 'hono/types'
Module Augmentation
Extend Hono’s types using module augmentation:
declare module 'hono' {
interface ContextVariableMap {
user : User
requestId : string
}
}
// Now these are available globally
app . get ( '/any-route' , ( c ) => {
const user = c . get ( 'user' ) // typed!
const requestId = c . get ( 'requestId' ) // typed!
return c . json ({ user , requestId })
})
RPC Type Safety
Get end-to-end type safety with Hono’s RPC client:
// server.ts
import { Hono } from 'hono'
const app = new Hono ()
. get ( '/posts/:id' , ( c ) => {
const id = c . req . param ( 'id' )
return c . json ({ id , title: 'Post Title' })
})
. post ( '/posts' , async ( c ) => {
const body = await c . req . json <{ title : string }>()
return c . json ({ id: '123' , ... body }, 201 )
})
export type AppType = typeof app
// client.ts
import { hc } from 'hono/client'
import type { AppType } from './server'
const client = hc < AppType >( 'http://localhost:3000' )
const res = await client . posts [ ':id' ]. $get ({
param: { id: '123' }
})
const data = await res . json () // fully typed!
Best Practices
Use type instead of interface for Env
Always use type to define your environment generics, not interface.
Define types at the app level
Define your environment types once when creating the Hono instance.
Let TypeScript infer types where possible instead of explicit annotations.
Use validation libraries with good types
Use Zod, Valibot, or similar libraries that provide excellent type inference.
Export your app type for RPC
Export your app type to enable type-safe RPC clients.