V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tlerbao
V2EX  ›  TypeScript

请教一个 Typescript 的问题

  •  
  •   tlerbao · 311 天前 · 2325 次点击
    这是一个创建于 311 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有两个响应类型 ResultData (不分页)和 ResultPage (分页),我下面封装的 get 方法每次调用的时候都要导入 ResultPage 或 ResultData ;

    http.get<ResultPage<SomeType>>("/test", params);

    http.get<ResultData<SomeType>>("/test", params);

    TS 有没有什么办法传入一个参数或怎样实现自动识别调用分页和不分页的类型?

    get<T>(url: string, params?: object, _object = {}): Promise<T> {
      return this.service.get(url, { params, ..._object });
    }
    
    // 请求响应
    export interface Result {
      code: string;
      message: string;
    }
    
    // 请求响应数据
    export interface ResultData<T = any> extends Result {
      data: T;
    }
    
    // 请求分页响应
    export interface ResultPage<T> extends Result {
      count: number;
      current: number;
      limit: number;
      data: T[];
    }
    
    14 条回复    2024-02-18 15:55:21 +08:00
    des
        1
    des  
       311 天前 via iPhone
    Promise<ResultPage<T>>
    des
        2
    des  
       311 天前 via iPhone
    @des 定义两个不同的 get ,getPage 和 getResult 吧
    pursuer
        3
    pursuer  
       311 天前
    大概试了一下类似这样
    interface test{
    (page:true):Promise<ResultPage>
    (page:false):Promise<ResultData>
    }
    let get:test=function(page){
    ...
    } as test;
    tlerbao
        4
    tlerbao  
    OP
       311 天前
    @des #2 定义两个 get 看来是比较简单的方法,但是为了学习更多的知识,不知道 typescript 有没有什么工具方法,或者传入两个泛型参数之类的(假设)。所以来问问
    xavierchow
        5
    xavierchow  
       311 天前
    > http.get<ResultPage<SomeType>>("/test", params);
    > 或
    > http.get<ResultData<SomeType>>("/test", params);

    这两个调用的参数一模一样,可以思考一下为什么你每次调用的时候知道该指定哪个返回类型?( ResultData VS ResultPage )
    是不是其实 params 的类型是不一样的?
    如果是的话,可以去定义 params 的类型,然后用 https://www.typescriptlang.org/docs/handbook/2/conditional-types.html , 大致思路就是用 param 的类型去确定响应的类型。

    另一个方式就是你去定义 UnionType ,比如 Result = ResultData | ResultPage, 你只用写 http.get<Resutl> ...
    然后在使用返回的响应值的地方,用 TypeGuard ( https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards )去 narrow down 具体的类型( ResultData VS ResultPage )
    zogwosh
        6
    zogwosh  
       311 天前

    用函数重载
    BeautifulSoap
        7
    BeautifulSoap  
       311 天前
    为什么一定要定义成接口,定义 ResultData 和 ResultPage 的 class 实现 Result 接口,然后传对应 class 的 object ,get 里用 instanceof 判断下不就解决的事情,,,,,,

    ts 编译时会把所有接口信息抹去,在接口上折腾没意义(虽然我不知道类型体操有没有黑魔法能做到)
    wusheng0
        8
    wusheng0  
       311 天前 via Android
    T extends Array ? ResultPage : ResultData 这种呢
    mmdsun
        9
    mmdsun  
       310 天前 via iPhone
    自定义类型?

    // 定义是否包含分页属性的类型检查
    type IsPaginated<Params> = Params extends { current: number; limit: number } ? true : false;

    // 结果类型的条件选择
    type DecideResult<T, Params> = IsPaginated<Params> extends true ? ResultPage<T> : ResultData<T>;
    tlerbao
        11
    tlerbao  
    OP
       310 天前
    @mmdsun 没太看懂怎么用呢?
    tlerbao
        12
    tlerbao  
    OP
       309 天前
    @zhours 学到了,
    但是在 page 的时候要先在前面写一个 never 感觉怪怪的也不语义化,还有更好的办法吗?大神
    const noPage = get<string>("");
    const Page = get<never, string>("");
    tlerbao
        14
    tlerbao  
    OP
       308 天前
    @zhours #13 感谢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   892 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 21:54 · PVG 05:54 · LAX 13:54 · JFK 16:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.