V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
ruandao
V2EX  ›  问与答

typescript 类型推导, 如何提取嵌入很深的类型(场景: swagger 生成接口类型后,怎么快速的提取需要的参数类型)

  •  
  •   ruandao · 2021-03-17 20:36:17 +08:00 · 846 次点击
    这是一个创建于 1348 天前的主题,其中的信息可能已经有所发展或是发生改变。

    嗯,通过 openapi-typescript 生成 swagger 的类型定义(类型定义文件内容如下)

    export interface paths {
      "/api/cusfood/create": {
        post: operations["controller-cusfood-create"];
      };
    }
    export interface definitions {
    cusfoodRequest: {
       	
      
        ch?: number;
      
        energy: number;
        
        fat?: number;
      
        protein?: number;
      };
      cusfoodResponse: {
        /** 状态码 */
        code: number;
        /** 具体数据 */
        data: definitions["cusfoodbody"];
        /** 是否成功 */
        success?: boolean;
      };
    }
    export interface operations {
      "controller-cusfood-create": {
        parameters: {
          body: {
            /** ( post 对应 body 请求,请求值设定为用户习惯信息 )。 */
            body: definitions["cusfoodRequest"];
          };
        };
        responses: {
          /** ( 响应 )。 */
          200: {
            schema: definitions["cusfoodResponse"];
          };
        };
      };
    }
    

    然后我想写个方便的泛型函数,来约束入参类型,以及方便编辑器提示出参类型

    const xFetch = <
        Path extends keyof paths,
        OpName extends keyof paths[Path],
        Query extends ???,
        Body extends ???,
        Resp extends ???
        >
    (path: Path, opName: OpName, query: Query, body: Body): Promise<Resp> => {
    // 由于 path + OpName 具有唯一性
    // 那么应该可以利用 typescript 里面的 可辨识联合 来推导出 Query, Body, Resp 的类型
    }
    
    

    求助

    谢谢

    4 条回复    2021-03-19 14:45:57 +08:00
    Sparetire
        1
    Sparetire  
       2021-03-18 01:45:33 +08:00 via Android
    Body extends Pick<Pick<Pick<operations, keyof operations>, 'parameters'>, 'body'>
    手机打字没测试。。不一定对
    Resp 类似
    Query
    type Key = string;
    type Value = string;
    type QS = '${Key}=${Value}';
    Query extends QS
    ruandao
        2
    ruandao  
    OP
       2021-03-18 19:40:58 +08:00
    @Sparetire 不大对,你这个方式 Pick 和 operations["xxx"] 能够得到一样的类型,但是这里想要的是 从 url 那边开始推导出类型,operations["xxx"] 得到的类型 无法关联到具体的类型
    RaminZhong
        3
    RaminZhong  
       2021-03-18 22:18:54 +08:00
    不太清楚你要的是哪种效果,试着写了下

    const xFetch = <
    Path extends keyof paths,
    OpName extends keyof paths[Path],
    Parameters extends paths[Path][OpName] extends { parameters: { query?: any; body?: any } }
    ? paths[Path][OpName]["parameters"]
    : { query: any; body: any }
    >(
    path: Path,
    opName: OpName,
    query: Parameters["query"]["query"],
    body: Parameters["body"]["body"]
    ): Promise<
    paths[Path][OpName] extends { responses: { [key: number]: { schema: any } } }
    ? paths[Path][OpName]["responses"][keyof paths[Path][OpName]["responses"]] extends { schema: any }
    ? paths[Path][OpName]["responses"][keyof paths[Path][OpName]["responses"]]["schema"]
    : any
    : any
    > => {
    return {} as any;
    };


    冗余地方有点多,你可以自行优化下
    Sparetire
        4
    Sparetire  
       2021-03-19 14:45:57 +08:00 via Android
    @ruandao 哦哦,不好意思理解错题意了,晚上脑子不太清醒。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1922 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:15 · PVG 00:15 · LAX 08:15 · JFK 11:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.