繁体   English   中英

打字稿 tapAsync 功能无法设置正确的打字

[英]Typescript tapAsync function unable to set correct typings

我希望能够使用 typescript 将几个 ES6 异步函数一起使用。 如果tap 函数没有返回任何内容,tap 函数应该返回参数,但如果tap 函数返回任何内容,则tap 返回值。

打字稿游乐场示例

我可以让它在不输入的情况下工作,但在设置类型时遇到问题。 有关在 Javascript 中工作的代码示例,请参阅代码段。

被抽头的函数被简单地用xx => fn(x)调用,然后链接以返回返回值y或抽头值x x => fn(x).then(y => y || x)

使用any类型的第一个版本可以工作,但是在具体处理轻敲函数中的类型时出现错误。

const tapAsync = (fn: (x: any) => Promise<any>) => (
  x: any
): Promise<any> => fn(x).then((y: any) => y || x)

为了更具体,我使用了两个泛型, X表示初始参数, Y表示抽头函数的返回值。

const tapAsync = (fn: <X>(x: X) => Promise<X>) => (
  x: X
): Promise<Y|X> => fn(x).then(<Y>(y: Y) => y || x)

当我使用 tapAsync 调用函数时,出现以下错误。

src/index.ts:45:18 - error TS2345: Argument of type '({ foo }: { foo: any; }) => Promise<void>' is not assignable to parameter of type '<X>(x: X) => Promise<X>'.
  Types of parameters '__0' and 'x' are incompatible.
    Type 'X' is not assignable to type '{ foo: any; }'.

45   .then(tapAsync(one))
                    ~~~
src/index.ts:46:18 - error TS2345: Argument of type '({ foo }: { foo: any; }) => Promise<{ foo: any; bar: string; }>' is not assignable to parameter of type '<X>(x: X) => Promise<X>'.
  Types of parameters '__0' and 'x' are incompatible.
    Type 'X' is not assignable to type '{ foo: any; }'.

46   .then(tapAsync(two))
                    ~~~
src/index.ts:47:18 - error TS2345: Argument of type '({ foo, bar }: { foo: any; bar: any; }) => Promise<void>' is not assignable to parameter of type '<X>(x: X) => Promise<X>'.
  Types of parameters '__0' and 'x' are incompatible.
    Type 'X' is not assignable to type '{ foo: any; bar: any; }'.

47   .then(tapAsync(three))

我不是在被轻敲功能打字稿设置任何类型的,但我一直在使用第二函数的两个泛型类型的尝试,但也不能正常工作

async function two<X>({ foo }): Promise<X> {
  console.log('two', foo)
  return {
    foo,
    bar: 'bar'
  }
}

 async function one({ foo }) { console.log('one', foo) } async function two({ foo }) { console.log('two', foo) return { foo, bar: 'bar' } } async function three({ foo, bar }) { console.log('three', foo, bar) } const tapAsync = fn => x => fn(x).then(y => y || x) Promise.resolve({ foo: 'foo' }) .then(tapAsync(one)) .then(tapAsync(two)) .then(tapAsync(three))

谢谢你的帮助!

============== 编辑 2020-09-01 ====================

我一直在玩代码并进一步充实了类型,但是现在当它返回一个新对象时,即使它是相同的形状,我也会在这两个函数上遇到错误。

新的打字稿游乐场示例

const tapAsync = <X, Y>(fn: (x: X) => Promise<Y|void>) => 
  (x: X): Promise<X|Y> => 
    fn(x).then((y: Y|void) => y || x)

我认为重载它可以工作。 并且类型推断看起来是正确的。 基本上这允许 ts 编译器推断永远不会有(x:X)=>Promise<void | Y> (x:X)=>Promise<void | Y>作为回报。 这发生了,因为在第一次调用非返回异步function :Promise<void> Y 被Promise.then(...为该类型,因此Promise.then(...将尝试将 X 作为 void | Args 在下一次调用,导致(x: void | Args)=>....这与(x: Args)=>...预期不兼容。

用重载检查这个操场你的例子

function tapAsync <X,Y>(fn: (x:X)=>Promise<void>): (x:X)=>Promise<X>;
function tapAsync <X,Y>(fn: (x:X)=>Promise<Y>): (x:X)=>Promise<Y>;
function tapAsync <X, Y>(fn: (x: X) => Promise<Y|void>) {
  return (x: X) => fn(x).then(y => y||x )
}

编辑:重读我的答案,我没有提到,罪魁祸首是(y: void| Y )=> Y||X无法推断如果初始 X 不是空的,它永远不会返回空。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM