1.0.9 • Published 10 months ago
@kiko-yd/easyts v1.0.9
EasyTs
一个为 TypeScript 项目设计的智能类型生成工具,适用于 Vue3 + vite 项目,可以自动拦截 API 响应并生成对应的 TypeScript 接口定义,极大提升开发效率。
✨ 特性
- 🚀 自动拦截 API 响应并生成 TypeScript 接口定义
- 📁 智能的类型文件管理系统
- 🔄 智能命名转换和类型推导
- 🔌 零侵入性集成
- 💪 完全类型安全
- 🎯 支持多种类型生成方式
📦 安装
npm install @kiko-yd/easyts⚙️ Vite 插件配置
在 vite.config.ts 中添加插件:
import { defineConfig } from "vite";
import { vitePluginEasyTs } from "@kiko-yd/easyts/vite-plugin-easyts";
export default defineConfig({
plugins: [
// ... 其他插件
vitePluginEasyTs(),
],
});🔨 环境区分
EasyTs 针对不同环境提供了智能的功能区分。这种区分的目的是:
优化生产环境性能
- 在生产环境中,类型生成和文件操作是完全不必要的,因为 TypeScript 类型仅在开发和编译时使用
- 禁用这些功能可以减少不必要的文件 I/O 操作和内存使用
- 避免在生产环境中生成大量临时文件
保持代码整洁
- 类型定义文件应该在开发阶段生成并提交到版本控制
- 避免在生产环境中出现重复或冗余的类型文件
- 保持项目结构的清晰和可维护性
类型工具不受影响
- 像
ModifyFields、ExtendField这样的类型工具在编译时使用 - 这些工具不会产生运行时开销,因此在所有环境中都可用
- 确保在生产环境中仍然可以使用类型扩展和重写功能
- 像
开发环境
在开发环境中,EasyTs 提供完整功能:
- ✅ 自动类型生成
- ✅ 类型文件管理
- ✅ 类型工具使用
- ✅ API 响应拦截
import { createEasyTs } from "@kiko-yd/easyts";
// 开发环境下默认启用所有功能
const easyTs = createEasyTs();
easyTs.start();
// 或者显式启用
const easyTs = createEasyTs({
enableTypeGeneration: true,
outputDir: "types/api",
});生产环境
在生产环境中,EasyTs 自动禁用类型生成相关功能,只保留类型工具:
- ❌ 自动类型生成(禁用)
- ❌ 类型文件管理(禁用)
- ✅ 类型工具使用(可用)
- ✅ API 响应拦截(可用)
import { createEasyTs, ModifyFields } from "@kiko-yd/easyts";
// 生产环境下自动禁用类型生成
const easyTs = createEasyTs();
// 类型工具在所有环境中可用
type CustomUser = ModifyFields<
UserData,
{
id: string;
age: string | number;
}
>;配置选项
interface EasyTsConfig {
/**
* 输出目录,相对于项目的src目录
* 默认为 'EasyTsApi'
*/
outputDir?: string;
/**
* 可选的 axios 实例
* 如果不提供,将创建一个新的实例
*/
axios?: AxiosInstance;
/**
* 是否启用类型生成功能
* 默认在开发环境下启用,生产环境下禁用
*/
enableTypeGeneration?: boolean;
}🔨 核心功能
1. createEasyTs
创建 EasyTs 实例,用于自动拦截 API 响应并生成类型定义。
import { createEasyTs } from "@kiko-yd/easyts";
// 基本使用
const easyTs = createEasyTs();
easyTs.start();
// 高级配置
const easyTs = createEasyTs({
outputDir: "types/api", // 自定义输出目录
axios: customAxios, // 自定义 axios 实例
});
// 项目实例
import axios from "axios";
import { createEasyTs } from "@kiko-yd/easyts";
const TIMEOUT_DURATION: number = 150000;
const instance: AxiosInstance = axios.create({
timeout: TIMEOUT_DURATION,
});
const easyTs = createEasyTs({
outputDir: "Interface",
axios: instance,
});
easyTs.start();
instance.interceptors.request.use(
(
config: InternalAxiosRequestConfig<any>
): InternalAxiosRequestConfig<any> => {
return config;
},
(error: AxiosError) => Promise.reject(error)
);
instance.interceptors.response.use(
(response: AxiosResponse): Promise<any> | AxiosResponse | any => {
return response.data;
},
(error) => {
const { response } = error;
return Promise.reject(error);
}
);
export default instance;使用场景:
- 在项目入口文件中初始化,自动监听所有 API 请求
- 需要自定义类型文件存储位置
- 使用自定义的 axios 实例时
2. createTypeInCurrentDir
在当前文件目录下快速生成类型定义文件。
import { createTypeInCurrentDir } from "@kiko-yd/easyts";
// 基本使用
const data = await fetchData();
await createTypeInCurrentDir(data, "UserTypes", import.meta.url);
// 导入生成的类型
import type { IGeneratedInterface } from "./UserTypes";参数说明:
data: any- 需要生成类型的数据fileName: string- 类型文件名(无需扩展名)filePath: string- 当前文件路径(使用 import.meta.url)
使用场景:
- 需要在组件/模块同级目录管理类型定义
- 快速为已有数据生成类型定义
- 希望类型文件与业务代码紧密关联
3. createTypeDefinition
将接口定义字符串保存为类型定义文件。
import { createTypeDefinition } from "@kiko-yd/easyts";
// 基本使用
const interfaceString = `
export interface UserData {
id: number;
name: string;
age: number;
}`;
await createTypeDefinition(interfaceString, "UserTypes");
// 生成文件:types/UserTypes.d.ts参数说明:
interfaceString: string- 接口定义字符串fileName?: string- 可选的文件名,默认为 "types"
使用场景:
- 已有接口定义需要保存为文件
- 需要将多个接口合并到一个文件
- 手动编写的接口需要规范化存储
4. getInterface
直接从数据生成 TypeScript 接口定义字符串。
import { getInterface } from "@kiko-yd/easyts";
const data = {
user: {
name: "张三",
age: 25,
hobbies: ["读书", "游戏"],
},
status: "active",
};
const interfaceString = getInterface(data);
console.log(interfaceString);输出示例:
export interface IGeneratedInterface {
user: {
name: string;
age: number;
hobbies: string[];
};
status: string;
}使用场景:
- 需要快速查看数据结构
- 临时生成接口定义
- 作为其他类型生成函数的基础
5. 类型重写与扩展
EasyTs 提供了三个实用的类型工具,用于重写或扩展自动生成的接口类型:
import type { OverrideField, ExtendField, ModifyFields } from "@kiko-yd/easyts";
// 假设自动生成的接口如下:
interface UserData {
id: number;
name: string;
age: number;
roles: string[];
profile: {
avatar: string;
bio: string;
};
}
// 1. 完全重写单个字段类型
type UserWithStringId = OverrideField<UserData, "id", string>;
// 结果:
// {
// id: string; // 类型被完全重写为 string
// name: string;
// age: number;
// ...
// }
// 2. 扩展单个字段类型(联合类型)
type UserWithFlexibleId = ExtendField<UserData, "id", string>;
// 结果:
// {
// id: number | string; // 原类型与新类型的联合
// name: string;
// age: number;
// ...
// }
// 3. 一次性修改多个字段类型(推荐)
type CustomUser = ModifyFields<
UserData,
{
id: string; // 完全重写为string
age: string | number; // 使用联合类型
roles: number[]; // 修改数组元素类型
profile: {
// 重写嵌套对象类型
avatar: string;
bio: string;
socialLinks: string[]; // 添加新字段
};
}
>;使用场景:
- API 返回的字段类型需要适配多种格式
- 需要扩展某些字段的类型范围
- 需要完全重写特定字段的类型
- 处理后端返回类型与前端实际使用类型不完全匹配的情况
- 需要批量修改多个字段类型时,使用
ModifyFields
🌰 最佳实践
1. API 请求类型生成
// api/user.ts
import { createEasyTs } from "@kiko-yd/easyts";
const easyTs = createEasyTs();
const axios = easyTs.getAxiosInstance();
// 自动生成类型并使用
export async function getUserInfo() {
const response = await axios.get("/api/user/info");
return response.data; // 类型会自动生成到 src/EasyTsApi/UserInfoResponse.ts
}2. 组件数据类型生成
// components/UserCard.vue
import { createTypeInCurrentDir } from "@kiko-yd/easyts";
// 生成类型
const mockData = {
title: "用户卡片",
user: { name: "张三", avatar: "url" },
};
await createTypeInCurrentDir(mockData, "UserCardTypes", import.meta.url);
// 使用生成的类型
import type { IGeneratedInterface as UserCardProps } from "./UserCardTypes";📝 注意事项
- 确保项目中有
src目录且具有写入权限 createTypeInCurrentDir必须使用import.meta.url作为第三个参数- 生成的类型文件建议加入版本控制
- 使用自定义 axios 实例时,确保在
start()前完成配置 - 类型文件名避免使用特殊字符
- 使用类型重写工具时,确保字段名称完全匹配
- 类型重写不会影响原始生成的类型文件,只在使用时生效
- 类型生成功能(如
createTypeDefinition、createTypeInCurrentDir)仅在开发环境可用 - 生产环境中调用类型生成功能会收到警告并安全返回空字符串
- 类型工具(如
ModifyFields、ExtendField)在所有环境中可用 - 可以通过
enableTypeGeneration配置手动控制类型生成功能的启用状态
🤝 贡献
欢迎提交 Issue 和 Pull Request!
📄 许可
MIT