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

2019-08-06 10:59:19 +08:00
 azh7138m

比如我的场景是这样的

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 内部会有一个微妙的报错(虽然不影响返回的类型)

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

2841 次点击
所在节点    问与答
7 条回复
whypool
2019-08-06 11:02:23 +08:00
那有没有低阶,中阶函数?
otakustay
2019-08-06 11:16:41 +08:00
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
2019-08-06 11:20:24 +08:00
首先,目前用 Function#apply 实质是没有类型检查的(不出错只是因为 apply 的参数是 any )

最外层可以这样写

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

里面人工保证吧
azh7138m
2019-08-06 11:29:52 +08:00
terax
2019-08-06 12:00:57 +08:00
@momocraft ts3.2 加入了 call apply 的严格类型检查,可以通过 -strictBindCallApply 打开
zbinlin
2019-08-06 22:26:18 +08:00
看下这样行不: //paste.ubuntu.com/p/c23DZyny3W/
azh7138m
2019-08-07 10:22:23 +08:00
@zbinlin 很棒
@momocraft @otakustay 楼上为目前最佳写法

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/589430

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX