首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带有Typescript和Axios的通用CRUD API客户端

带有Typescript和Axios的通用CRUD API客户端
EN

Stack Overflow用户
提问于 2019-07-24 18:51:31
回答 1查看 1.2K关注 0票数 1

我正在尝试使用Axios在Typescript中为我的API实现一个通用的CRUD接口。

假设API公开了用于对2个实体执行CRUD操作的端点。假设端点是/users/posts/,并且这两个端点都采用offsetcount参数(用于分页)。响应示例:

代码语言:javascript
运行
复制
GET /users?offset=2&count=2

{
  "users": ["user1", "user2"],
  "total": 4 // the total number of users that exist
}

与此类似,对于posts,帖子数组的关键字是`“post”。

我尝试创建一个通用函数来获取用户/帖子,如下所示:

代码语言:javascript
运行
复制
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;
  };

其中,UserPost接口均继承的Persistable接口和PaginatedResponse接口如下所示:

代码语言:javascript
运行
复制
export interface PaginatedResponse<T> {
  readonly total: number;
  readonly items: T[];
}

基本上,我需要填充<BLANK>,例如,根据传递的类型T,以某种方式分别获取字符串"users"/"posts"

有人能想出一种方法来实现这一点吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-07-24 19:41:21

我可能会建议以下使用函数重载的解决方案。在这种情况下,我不会使用泛型重新注释,因为T仅限于userpost。由于TypeScript接口与形状有关,因此通过泛型,T实际上可以是任何扩展Persistable的东西

我曾设想用户和帖子将不是字符串数组,而是对象数组。type属性将创建discriminated union,并将在编译后保留。

我已经向getPage函数添加了额外的参数reqType来区分用户和posts请求。reqType可以是'user''post'。其他值将导致错误。

User['type']indexed access operator,因此如果您将来要添加另一种类型的响应,reqType将自动填充type值。

代码语言:javascript
运行
复制
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>>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57181194

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档