typescript - 带有 Typescript 和 Axios 的通用 CRUD API 客户端
问题描述
我正在尝试使用 Axios 在 Typescript 中为我的 API 实现通用 CRUD 接口。
假设 API 公开了使用 2 个实体执行 CRUD 操作的端点。假设端点是/users
并且/posts/
都采用 URL 参数offset
和count
(用于分页)。响应示例:
GET /users?offset=2&count=2
{
"users": ["user1", "user2"],
"total": 4 // the total number of users that exist
}
类似地posts
,帖子数组的键是“帖子”。
我试图创建一个通用函数来获取用户/帖子,如下所示:
export const getPage =
async <T extends Persistable>(offset: number, count: number): Promise<PaginatedResponse<T>> => {
const response = await axios.get<PaginatedResponse<T>>(
`${SOME_URL}/<BLANK>`,
{
params: { page, size },
transformResponse: [
(data) => ({
...data,
items: data[<BLANK>],
})
]
},
);
return response.data;
};
和接口Persistable
都继承自和User
接口的接口如下所示:Post
PaginatedResponse
export interface PaginatedResponse<T> {
readonly total: number;
readonly items: T[];
}
基本上,我需要通过例如基于传递的 type<BLANK>
以某种方式获取字符串"users"
/来填写 s 。"posts"
T
请问有人能想出一种方法来实现这一点吗?
解决方案
我可能会建议使用函数重载来遵循解决方案。我不建议在这种情况下使用泛型,因为T
它仅限于user
or 或post
. 由于 TypeScript 接口与形状有关,因此泛型T
几乎可以是任何可以扩展的东西Persistable
我想象用户和帖子不会是字符串数组,而是对象数组。type
属性将创建可区分的联合并在编译后保留。
我添加了额外的参数reqType
来getPage
区分用户和帖子请求。reqType
可能是'user'
或'post'
。其他值会导致错误。
这User['type']
是索引访问运算符,因此如果您将来添加另一种类型的响应,reqType 将自动填充type
值。
type User = { type: 'user', user: string };
type Post = { type: 'post', post: string };
export interface PaginatedResponse<T> {
readonly total: number;
readonly items: T[];
}
// This is type guard which will stay in run time
function reqTypeIsUser(a: User['type'] | Post['type']): a is User['type'] {
return (a as User['type']) === 'user'
}
async function getPage
(offset: number, count: number, reqType: User['type']): Promise<PaginatedResponse<User>>
async function getPage
(offset: number, count: number, reqType: Post['type']): Promise<PaginatedResponse<Post>>
async function getPage
(offset: number, count: number, reqType: User['type'] | Post['type']): Promise<PaginatedResponse<User | Post>> {
const response = await axios.get<PaginatedResponse<User | Post>>(
'url' + reqTypeIsUser(reqType) ? 'users' : 'posts',
{
params: { offset, count },
transformResponse: [
(data) => ({
...data,
items: data[reqType].map((d: string) => ({ type: reqType, [reqType]: d })),
})
]
},
);
return response.data;
};
let user = getPage(1, 2, "user"); // user will be Promise<PaginatedResponse<User>>
推荐阅读
- android - 如何从 Travis 构建中知道确切的错误
- javascript - 单线程问题上的旧异步 - 受 Node JS 启发
- python - 为什么 (?
m = re.match('(?<!index)\.html?', 'abc.html') print(m)
无法匹配,在我的记忆中它应该可以工作......我是一个菜鸟,请帮助我。多谢。
如何用php计算数组空值?
- php - 如何用php计算数组空值?
- javascript - JavaScript 函数返回“非法返回语句”
- jqgrid - jqGrid getRowData 返回空对象
- swift - Swift 桥接 2D 数组以键入 UnsafePointer
?>? - sql - SQLite JOIN WHERE 不在多个表中
- linux - 如何使用 linux free 命令向我的脚本添加时间戳 (free | grep mem | awk '{print $4/$2 * 100.0}')
- macos - 您无权访问此服务器上的 / - Mac OS X Mojave 上的 Apache 2