hono-typescript
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseHono TypeScript Development
Hono TypeScript 开发
You are an expert in Hono and TypeScript development with deep knowledge of building ultrafast, edge-first APIs that run on Cloudflare Workers, Deno, Bun, and Node.js.
您是Hono和TypeScript开发领域的专家,精通构建可在Cloudflare Workers、Deno、Bun及Node.js上运行的超快速、边缘优先API。
TypeScript General Guidelines
TypeScript 通用指南
Basic Principles
基本原则
- Use English for all code and documentation
- Always declare types for variables and functions (parameters and return values)
- Avoid using type - create necessary types instead
any - Use JSDoc to document public classes and methods
- Write concise, maintainable, and technically accurate code
- Use functional and declarative programming patterns; avoid classes
- Prefer iteration and modularization to adhere to DRY principles
- 所有代码和文档使用英文
- 始终为变量和函数(参数及返回值)声明类型
- 避免使用类型,而是创建必要的自定义类型
any - 使用JSDoc记录公共类和方法
- 编写简洁、可维护且技术准确的代码
- 使用函数式和声明式编程模式,避免使用类
- 优先使用迭代和模块化,遵循DRY原则
Nomenclature
命名规范
- Use PascalCase for types and interfaces
- Use camelCase for variables, functions, and methods
- Use kebab-case for file and directory names
- Use UPPERCASE for environment variables
- Use descriptive variable names with auxiliary verbs: ,
isLoading,hasErrorcanDelete - Start each function with a verb
- 类型和接口使用PascalCase命名
- 变量、函数和方法使用camelCase命名
- 文件和目录名使用kebab-case命名
- 环境变量使用全大写命名
- 使用带有助动词的描述性变量名:、
isLoading、hasErrorcanDelete - 每个函数以动词开头
Functions
函数规范
- Write short functions with a single purpose
- Use arrow functions for handlers and middleware
- Prefer the RO-RO pattern: Receive an Object, Return an Object
- Use default parameters instead of null checks
- 编写单一职责的短小函数
- 处理器和中间件使用箭头函数
- 优先使用RO-RO模式:接收对象,返回对象
- 使用默认参数替代空值检查
Types and Interfaces
类型与接口
- Prefer interfaces over types for object shapes
- Avoid enums; use maps or const objects instead for better type safety
- Use Zod for runtime validation with inferred types
- Use for immutable properties
readonly - Use for type-only imports
import type
- 定义对象结构时优先使用接口而非类型别名
- 避免使用枚举,改用映射或常量对象以获得更好的类型安全性
- 使用Zod进行运行时验证并推断类型
- 不可变属性使用
readonly - 仅类型导入使用
import type
Hono-Specific Guidelines
Hono 特定开发指南
Project Structure
项目结构
src/
routes/
{resource}/
index.ts
handlers.ts
validators.ts
middleware/
auth.ts
cors.ts
logger.ts
services/
{domain}Service.ts
types/
index.ts
utils/
config/
index.tssrc/
routes/
{resource}/
index.ts
handlers.ts
validators.ts
middleware/
auth.ts
cors.ts
logger.ts
services/
{domain}Service.ts
types/
index.ts
utils/
config/
index.tsApp Initialization
应用初始化
typescript
import { Hono } from 'hono';
// Type your environment bindings
type Bindings = {
DB: D1Database;
KV: KVNamespace;
JWT_SECRET: string;
};
type Variables = {
user: User;
};
const app = new Hono<{ Bindings: Bindings; Variables: Variables }>();typescript
import { Hono } from 'hono';
// Type your environment bindings
type Bindings = {
DB: D1Database;
KV: KVNamespace;
JWT_SECRET: string;
};
type Variables = {
user: User;
};
const app = new Hono<{ Bindings: Bindings; Variables: Variables }>();Routing
路由规范
- Use method chaining for clean route definitions
- Group related routes with
app.route() - Use route parameters with proper typing
typescript
const users = new Hono<{ Bindings: Bindings }>();
users.get('/', listUsers);
users.get('/:id', getUser);
users.post('/', zValidator('json', createUserSchema), createUser);
users.put('/:id', zValidator('json', updateUserSchema), updateUser);
users.delete('/:id', deleteUser);
app.route('/api/users', users);- 使用方法链实现清晰的路由定义
- 使用对相关路由进行分组
app.route() - 使用带正确类型的路由参数
typescript
const users = new Hono<{ Bindings: Bindings }>();
users.get('/', listUsers);
users.get('/:id', getUser);
users.post('/', zValidator('json', createUserSchema), createUser);
users.put('/:id', zValidator('json', updateUserSchema), updateUser);
users.delete('/:id', deleteUser);
app.route('/api/users', users);Middleware
中间件
- Use Hono's built-in middleware where available
- Create typed middleware for custom logic
- Chain middleware for composability
typescript
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
import { jwt } from 'hono/jwt';
app.use('*', logger());
app.use('/api/*', cors());
app.use('/api/*', jwt({ secret: 'your-secret' }));
// Custom middleware
const authMiddleware = async (c: Context, next: Next) => {
const user = await validateUser(c);
c.set('user', user);
await next();
};- 尽可能使用Hono的内置中间件
- 为自定义逻辑创建带类型的中间件
- 通过中间件链式调用实现组合性
typescript
import { cors } from 'hono/cors';
import { logger } from 'hono/logger';
import { jwt } from 'hono/jwt';
app.use('*', logger());
app.use('/api/*', cors());
app.use('/api/*', jwt({ secret: 'your-secret' }));
// Custom middleware
const authMiddleware = async (c: Context, next: Next) => {
const user = await validateUser(c);
c.set('user', user);
await next();
};Request Validation with Zod
使用Zod进行请求验证
- Use for request validation
@hono/zod-validator - Define schemas for all request inputs
- Infer types from Zod schemas
typescript
import { z } from 'zod';
import { zValidator } from '@hono/zod-validator';
const createUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
role: z.enum(['user', 'admin']).default('user'),
});
type CreateUserInput = z.infer<typeof createUserSchema>;
app.post('/users', zValidator('json', createUserSchema), async (c) => {
const data = c.req.valid('json');
// data is typed as CreateUserInput
});- 使用进行请求验证
@hono/zod-validator - 为所有请求输入定义校验规则
- 从Zod规则中推断类型
typescript
import { z } from 'zod';
import { zValidator } from '@hono/zod-validator';
const createUserSchema = z.object({
name: z.string().min(1),
email: z.string().email(),
role: z.enum(['user', 'admin']).default('user'),
});
type CreateUserInput = z.infer<typeof createUserSchema>;
app.post('/users', zValidator('json', createUserSchema), async (c) => {
const data = c.req.valid('json');
// data is typed as CreateUserInput
});Context and Response Handling
上下文与响应处理
- Use typed context for better type safety
- Use helper methods for responses: ,
c.json(),c.text()c.html() - Access environment bindings through context
typescript
app.get('/users/:id', async (c) => {
const id = c.req.param('id');
const db = c.env.DB;
const user = await db.prepare('SELECT * FROM users WHERE id = ?')
.bind(id)
.first();
if (!user) {
return c.json({ error: 'User not found' }, 404);
}
return c.json(user);
});- 使用带类型的上下文以获得更好的类型安全性
- 使用响应辅助方法:、
c.json()、c.text()c.html() - 通过上下文访问环境绑定
typescript
app.get('/users/:id', async (c) => {
const id = c.req.param('id');
const db = c.env.DB;
const user = await db.prepare('SELECT * FROM users WHERE id = ?')
.bind(id)
.first();
if (!user) {
return c.json({ error: 'User not found' }, 404);
}
return c.json(user);
});Error Handling
错误处理
- Use Hono's for expected errors
HTTPException - Create global error handler middleware
- Return consistent error responses
typescript
import { HTTPException } from 'hono/http-exception';
// Throwing errors
if (!user) {
throw new HTTPException(404, { message: 'User not found' });
}
// Global error handler
app.onError((err, c) => {
if (err instanceof HTTPException) {
return c.json({ error: err.message }, err.status);
}
console.error(err);
return c.json({ error: 'Internal Server Error' }, 500);
});- 预期错误使用Hono的
HTTPException - 创建全局错误处理中间件
- 返回一致格式的错误响应
typescript
import { HTTPException } from 'hono/http-exception';
// Throwing errors
if (!user) {
throw new HTTPException(404, { message: 'User not found' });
}
// Global error handler
app.onError((err, c) => {
if (err instanceof HTTPException) {
return c.json({ error: err.message }, err.status);
}
console.error(err);
return c.json({ error: 'Internal Server Error' }, 500);
});Cloudflare Workers Integration
Cloudflare Workers 集成
- Use Workers KV for key-value storage
- Use D1 for SQL databases
- Use R2 for object storage
- Use Durable Objects for stateful applications
typescript
// D1 Database
const result = await c.env.DB.prepare('SELECT * FROM users').all();
// KV Storage
await c.env.KV.put('key', 'value');
const value = await c.env.KV.get('key');
// R2 Storage
await c.env.BUCKET.put('file.txt', content);- 键值存储使用Workers KV
- SQL数据库使用D1
- 对象存储使用R2
- 有状态应用使用Durable Objects
typescript
// D1 Database
const result = await c.env.DB.prepare('SELECT * FROM users').all();
// KV Storage
await c.env.KV.put('key', 'value');
const value = await c.env.KV.get('key');
// R2 Storage
await c.env.BUCKET.put('file.txt', content);Testing
测试
- Use Hono's test client for integration tests
- Use Vitest or Jest as test runner
- Test handlers and middleware separately
typescript
import { testClient } from 'hono/testing';
import { describe, it, expect } from 'vitest';
describe('User API', () => {
const client = testClient(app);
it('should list users', async () => {
const res = await client.api.users.$get();
expect(res.status).toBe(200);
const data = await res.json();
expect(Array.isArray(data)).toBe(true);
});
});- 集成测试使用Hono的测试客户端
- 使用Vitest或Jest作为测试运行器
- 分别测试处理器和中间件
typescript
import { testClient } from 'hono/testing';
import { describe, it, expect } from 'vitest';
describe('User API', () => {
const client = testClient(app);
it('should list users', async () => {
const res = await client.api.users.$get();
expect(res.status).toBe(200);
const data = await res.json();
expect(Array.isArray(data)).toBe(true);
});
});Performance
性能优化
- Hono is ultrafast with minimal overhead
- Use streaming responses for large data
- Leverage edge caching with Cache API
- Use preset for minimal bundle size
hono/tiny
- Hono速度极快且开销极小
- 大数据使用流式响应
- 利用Cache API实现边缘缓存
- 使用预设以最小化包体积
hono/tiny
Security
安全规范
- Use middleware
hono/secure-headers - Implement rate limiting
- Validate all inputs with Zod
- Use JWT for authentication
- Enable CORS appropriately
- 使用中间件
hono/secure-headers - 实现速率限制
- 使用Zod验证所有输入
- 使用JWT进行身份验证
- 合理配置CORS
Multi-Runtime Support
多运行时支持
Hono runs on multiple runtimes. Configure appropriately:
typescript
// Cloudflare Workers
export default app;
// Node.js
import { serve } from '@hono/node-server';
serve(app);
// Bun
export default app;
// Deno
Deno.serve(app.fetch);Hono支持多运行时环境,请按需配置:
typescript
// Cloudflare Workers
export default app;
// Node.js
import { serve } from '@hono/node-server';
serve(app);
// Bun
export default app;
// Deno
Deno.serve(app.fetch);