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

TS 类型问题 高阶函数如何写类型

  •  
  •   azh7138m · 2019-08-06 10:59:19 +08:00 · 2842 次点击
    这是一个创建于 1971 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如我的场景是这样的

    async function doRequest({ type }) {
        
    }
    
    function wrapper<T>(fn: (arg: T) => Promise<void>): (arg: T) => Promise<void>{
        return async function(...args) {
            await fn.apply(null, args);
        };
    }
    
    const myDoRequest = wrapper(doRequest);
    

    这样写,doRequest的类型( (arg: { type: any; }) => Promise<void> )符合我的预期。

    现在我想扩展一下 wrapper 到支持多个参数,但是下述两种写法都是不行的

    async function doRequest({ type, }, { no }) {
        
    }
    
    function wrapper<T>(fn: (...args: T[]) => Promise<void>): (...arg: T[]) => Promise<void>{
        return async function(...args) {
            await fn.apply(null, args);
        };
    }
    
    const myDoRequest = wrapper(doRequest);
    
    async function doRequest({ type, }, { no }) {
        
    }
    
    function wrapper<T extends Function>(fn: T): T{
        return async function(...args) {
            await fn.apply(null, args);
        };
    }
    
    const myDoRequest = wrapper(doRequest);
    

    这个 wrapper 内部会有一个微妙的报错(虽然不影响返回的类型)

    问题 这种高阶函数正确的类型是什么呢?

    第 1 条附言  ·  2020-07-06 23:47:50 +08:00
    哎 链接要过期了,补一下
    7 条回复    2019-08-07 10:22:23 +08:00
    whypool
        1
    whypool  
       2019-08-06 11:02:23 +08:00
    那有没有低阶,中阶函数?
    otakustay
        2
    otakustay  
       2019-08-06 11:16:41 +08:00   ❤️ 1
    function wrapper<T1>(fn: (arg: T1) => Promise<void>): (arg: T1) => Promise<void>
    function wrapper<T1, T2>(fn: (arg1: T1, arg2: T2) => Promise<void>): (arg1: T1, arg2: T2) => Promise<void>
    function wrapper<T1, T2, T3>(fn: (arg1: T1, arg2: T2, arg3: T3) => Promise<void>): (arg1: T1, arg2: T2, arg3: T3) => Promise<void>

    连着这样写 10 个,是 ts 的常用手段
    momocraft
        3
    momocraft  
       2019-08-06 11:20:24 +08:00   ❤️ 1
    首先,目前用 Function#apply 实质是没有类型检查的(不出错只是因为 apply 的参数是 any )

    最外层可以这样写

    ```
    function wrapper<T extends Function>(fn: T): typeof fn {
    }
    ```

    里面人工保证吧
    terax
        5
    terax  
       2019-08-06 12:00:57 +08:00 via iPhone   ❤️ 1
    @momocraft ts3.2 加入了 call apply 的严格类型检查,可以通过 -strictBindCallApply 打开
    zbinlin
        6
    zbinlin  
       2019-08-06 22:26:18 +08:00   ❤️ 2
    看下这样行不: //paste.ubuntu.com/p/c23DZyny3W/
    azh7138m
        7
    azh7138m  
    OP
       2019-08-07 10:22:23 +08:00
    @zbinlin 很棒
    @momocraft @otakustay 楼上为目前最佳写法
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2873 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 08:29 · PVG 16:29 · LAX 00:29 · JFK 03:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.