name: frontend-types
description: 所有TypeScript类型定义都在frontend/types/index.ts文件中。类型与后端API响应结构匹配,为前端应用提供类型安全。
前端TypeScript类型技能
目的: 指导如何按照frontend/types/index.ts中的现有模式创建TypeScript类型定义。
概述
所有TypeScript类型都定义在frontend/types/index.ts文件中。类型与后端API响应结构匹配,为前端应用提供类型安全。
来自frontend/types/index.ts的类型模式
1. 用户类型
export interface User {
id: string;
email: string;
name: string;
createdAt?: string;
updatedAt?: string;
}
export interface UserCredentials {
email: string;
password: string;
}
export interface UserSignupData extends UserCredentials {
name: string;
}
模式:
- 对象类型使用
interface - 可选字段用
?标记 - 类型继承使用
extends - 前端类型使用camelCase(即使后端使用snake_case)
2. 任务类型
export type TaskStatus = "pending" | "completed";
export type TaskPriority = "low" | "medium" | "high";
export interface Task {
id: number;
user_id: string;
title: string;
description?: string;
completed: boolean;
priority: TaskPriority;
due_date?: string;
tags: string[];
created_at: string;
updated_at: string;
}
export interface TaskFormData {
title: string;
description?: string;
priority?: TaskPriority;
due_date?: string;
tags?: string[];
}
export interface TaskQueryParams {
status?: "all" | "pending" | "completed";
sort?: "created" | "title" | "updated" | "priority" | "due_date";
search?: string;
page?: number;
limit?: number;
}
模式:
- 联合类型使用
type(字符串字面量) - 对象类型使用
interface - 匹配后端字段名(API字段使用snake_case,如
user_id、due_date、created_at) - 为表单数据创建单独的类型(除必填字段外全部可选)
- 为查询参数创建单独的类型(全部可选)
3. API响应类型
export interface ApiResponse<T = unknown> {
data?: T;
success: boolean;
message?: string;
error?: {
code: string;
message: string;
details?: unknown;
};
}
export interface PaginatedResponse<T> {
data: T[];
meta: {
total: number;
page: number;
limit: number;
totalPages: number;
};
}
模式:
- 可重用结构使用泛型类型
<T> - 提供默认类型参数(
<T = unknown>) - 包含
success布尔标志 - 包含可选的
data、message和error字段 - 为分页响应创建单独的类型,包含
meta对象
4. 认证类型
export interface AuthResponse {
success: boolean;
token: string;
user: User;
}
export interface Session {
user: User;
token: string;
expiresAt: number;
}
模式:
- 包含
success布尔值 - 包含
token字符串 - 包含
user对象(User类型) - 会话包含
expiresAt时间戳
5. 错误类型
export interface AppError {
message: string;
code?: string;
statusCode?: number;
field?: string;
}
export interface FormErrors {
[key: string]: string | undefined;
}
模式:
- 错误对象使用
interface - 可选字段用
?标记 - 动态对象类型使用索引签名
[key: string](FormErrors)
6. UI类型
export type LoadingState = "idle" | "loading" | "success" | "error";
export type ToastType = "success" | "error" | "warning" | "info";
export interface ToastMessage {
id: string;
type: ToastType;
message: string;
duration?: number;
}
模式:
- 联合类型使用
type(字符串字面量) - 对象类型使用
interface - 包含
id用于唯一标识 - 可选字段用
?标记
7. 导出/导入类型
export type ExportFormat = "csv" | "json";
export interface ImportResult {
imported: number;
errors: number;
errorDetails?: string[];
}
模式:
- 联合类型使用
type(字符串字面量) - 结果对象使用
interface - 包含成功/错误跟踪的计数
- 包含可选的错误详情数组
类型命名约定
接口
- PascalCase:
User、Task、ApiResponse - 描述性名称:
TaskFormData、UserSignupData
类型(联合类型)
- PascalCase:
TaskStatus、TaskPriority、LoadingState - 描述性名称:
ToastType、ExportFormat
Props类型
- 组件名 + Props:
TaskItemProps、ProtectedRouteProps - 示例:
interface TaskItemProps { task: Task; }
表单数据类型
- 实体名 + FormData:
TaskFormData、UserSignupData - 示例:
interface TaskFormData { title: string; description?: string; }
查询参数类型
- 实体名 + QueryParams:
TaskQueryParams - 示例:
interface TaskQueryParams { status?: "all" | "pending" | "completed"; }
匹配后端模式
字段名映射
后端(snake_case) → 前端(表单数据用camelCase,API响应用snake_case)
// 后端API响应(与后端完全匹配)
export interface Task {
id: number;
user_id: string; // 来自后端的snake_case
title: string;
due_date?: string; // 来自后端的snake_case
created_at: string; // 来自后端的snake_case
updated_at: string; // 来自后端的snake_case
}
// 前端表单数据(使用camelCase便于前端使用)
export interface TaskFormData {
title: string;
dueDate?: string; // 前端的camelCase
tags?: string[];
}
模式:
- API响应类型与后端完全匹配(snake_case)
- 表单数据类型使用camelCase便于前端使用
- 与API发送/接收时在格式间转换
必填字段与可选字段
// 后端API响应(来自后端的所有字段)
export interface Task {
id: number; // 必填(来自后端)
user_id: string; // 必填(来自后端)
title: string; // 必填(来自后端)
description?: string; // 可选(来自后端)
completed: boolean; // 必填(来自后端)
priority: TaskPriority; // 必填(来自后端)
due_date?: string; // 可选(来自后端)
tags: string[]; // 必填(来自后端,可以是空数组)
created_at: string; // 必填(来自后端)
updated_at: string; // 必填(来自后端)
}
// 前端表单数据(仅用户可编辑的字段)
export interface TaskFormData {
title: string; // 必填(用户必须提供)
description?: string; // 可选
priority?: TaskPriority; // 可选(有默认值)
due_date?: string; // 可选
tags?: string[]; // 可选(可以是空数组)
}
模式:
- API响应类型包含来自后端的所有字段
- 表单数据类型仅包含用户可编辑的字段
- 可选字段用
?标记 - 必填字段没有
?
类型结构模式
1. 对象使用interface
export interface User {
id: string;
email: string;
}
何时使用: 具有属性的对象类型
2. 联合、交集或别名使用type
export type TaskStatus = "pending" | "completed";
export type TaskPriority = "low" | "medium" | "high";
何时使用: 联合类型、交集或类型别名
3. 可重用结构使用泛型类型
export interface ApiResponse<T = unknown> {
data?: T;
success: boolean;
}
何时使用: 可与不同类型一起使用的可重用结构
4. 可选属性用?标记
export interface Task {
title: string; // 必填
description?: string; // 可选
}
何时使用: 可能不存在的字段
完整示例:添加新类型
步骤1:定义实体类型(匹配后端)
export interface Category {
id: number;
user_id: string;
name: string;
color?: string;
created_at: string;
updated_at: string;
}
步骤2:定义表单数据类型(用于用户输入)
export interface CategoryFormData {
name: string;
color?: string;
}
步骤3:定义查询参数类型(用于API查询)
export interface CategoryQueryParams {
search?: string;
page?: number;
limit?: number;
}
步骤4:在API客户端中使用
async getCategories(
userId: string,
queryParams?: CategoryQueryParams
): Promise<ApiResponse<PaginatedResponse<Category>>> {
// 实现
}
宪法要求
- FR-030: 所有API调用的TypeScript接口类型 ✅
- FR-037: TypeScript严格模式 ✅
参考资料
- 规范:
specs/002-frontend-todo-app/spec.md- 实体定义 - 计划:
specs/002-frontend-todo-app/plan.md- 带类型的API契约 - 类型文件:
frontend/types/index.ts- 完整的类型定义
常见模式总结
- ✅ 对象类型使用
interface - ✅ 联合类型(字符串字面量)使用
type - ✅ 可重用结构使用泛型类型
<T> - ✅ 可选字段用
?标记 - ✅ 匹配后端字段名(API响应使用snake_case)
- ✅ 表单数据类型使用camelCase
- ✅ 为表单数据和查询参数创建单独的类型
- ✅ 使用描述性名称(EntityFormData、EntityQueryParams)
- ✅ 包含来自后端的所有必填字段
- ✅ 为泛型提供默认类型参数(
<T = unknown>)