写在前面
在 TypeScript 项目中,处理接口返回数据类型,是日常项目开发中一个比较棘手的问题。
我们该如何 高效 的解决这个问题?
问题
项目中使用 ts 都会碰到如下场景?
const fetchInfo = async (url: string, id: string) => {
return $http.get(url, params);
}
const res = await fetchInfo('/info', '886');
// 假设 `/info` 接口返回如下数据
{ id: '886', 🙈:{ name: 'Jack', 📱: { brand: 'Chinese Pineapple' } } }
接口返回过来的数据,在上面代码中如何得到 🙈 的名字以及使用的 📱 品牌呢?
解答
目前比较常用的写法有以下两种
-
any大法:const res:any = await fetchInfo('/info', '886'); console.log(res.🙈.name) // Jack console.log(res.🙈.📱.brand) // Chinese Pineapple -
更加优雅的
interface写法:/** 根据接口返回的数据,声明对应的 interface **/ interface Info { id: string; 🙈: Monkey; } interface Monkey { name: string; 📱: Phone; } interface Phone { brand: string; } /** 改写 `fetchInfo` 函数返回值类型 **/ const fetchInfo = async (url: string, id: string): Promise<Info> => { return $http.get(url, params); } const res = await fetchInfo('/info', '886'); console.log(res.🙈.name) // Jack console.log(res.🙈.📱.brand) // Chinese Pineapple
区别
两种实现方式的区别十分明显:
-
any大法- ✨ 前期开发代码量少,快速简单。
- 🚨 由于未定义
interface导致整个项目充斥着大量any类型,项目沦为AnyScript。 - 🚨 无法获得健全的
ts语法检测功能,弱化了使用ts的作用。 - 🚨 后期维护成本高,后端修改字段,调用处需要一一核查。
-
interface- 🚨 前期开发代码量大,需要为每个接口定义
interface。 - ✨ 获得丰富的代码提示以及语法检测能力。
- ✨ 后期项目易维护,接口字段改动,只需要同步更新
interface数据即可实现类型检测。
- 🚨 前期开发代码量大,需要为每个接口定义
总结
通过上面的总结不难看出,interface 方式优势众多,但同时也有着一个致命的弊端:
我们在前期的开发过程中需要对所有接口返回的不同数据类型定义对应的 interface。
例如上面示例的 /info 接口我们就需要定义三个 interface ,实际项目中,字段数量可能达到几十上百个!
interface Info {
id: string;
🙈: Monkey;
}
interface Monkey {
name: string;
📱: Phone;
}
interface Phone {
brand: string;
}
这对于我们前期开发效率来说无疑是 毁灭性 的💥💥💥
🚀 必备高效神器
基于上面 interface 方式所面临的问题
给大家安利一款前端在线代码生成工具:JsonToAny ( Gitee / GitHub )
能够很轻松的将接口返回的 JSON 数据转换成前端所需要的 interface
最大程度的节省了我们手动定义 interface 的时间
至此,我们完美解决的了 interface 方式最大的弊端,一劳永逸🎉。