打字稿调用签名推断

时间:2017-11-30 18:10:14

标签: typescript flowtype

我正在尝试将以下Flow片段转换为Typescript:

type Handler<Data> = (data: Data) => void
type Foo = { foo: string }
type AnyRequest = (path: '/foo', handler: Handler<Foo>) => void
type FooRequest = (path: string, handler: Handler<any>) => void

type RouterRequest = AnyRequest | FooRequest


function router(request: RouterRequest) {
   request('/foo', (data) => {
      // here data should be of type Foo
   })

   request('/bar', (data) => {
      // here data should be of type any  
   })  
}

此处的流程可以使用data参数正确推断出path的类型。见running snippet

Typescript中的相同代码无法推断出data的类型 在playground中粘贴此代码会给我这个错误

  

无法调用类型缺少调用签名的表达式。输入&#39; RouterRequest&#39;没有兼容的呼叫签名。

有没有办法在Typescript中实现类似的东西?

3 个答案:

答案 0 :(得分:2)

认为你的意思是RouterRequestAnyRequestFooRequest交集,而不是他们的 union < / em>的。像这样:

type RouterRequest = AnyRequest & FooRequest;

类型AnyRequest | FooRequest指的是您不知道它是AnyRequest还是FooRequest的内容。 TypeScript或多或少警告你它不知道它是哪一个所以它根本不会让你调用它(虽然它可能should让你用参数的交集调用它,但是我离题。)

但是你希望能够用任何一组参数来调用它。这更像是overloaded function(或函数类型的交集)而不是联合。

如果您更改上面的行,它应该适合您,假设RouterRequest确实可以通过两种方式调用。

希望有所帮助;祝你好运!

答案 1 :(得分:2)

这是RouterRequest类型,允许完整的上下文输入...

type RouterRequest = {
  (path: "/foo", handler: Handler<Foo>): void;
  (path: string, handler: Handler<any>): void;
}

完整示例:

type Handler<Data> = (data: Data) => void;
type Foo = { foo: string }

type RouterRequest = {
  (path: "/foo", handler: Handler<Foo>): void;
  (path: string, handler: Handler<any>): void;
}

function router(request: RouterRequest) {
    request('/foo', (data) => {
        // data is of type Foo
    })

    request('/bar', (data) => {
        // data is of type any  
    })  
}

答案 2 :(得分:0)

这将有效:

type RouterRequest = {
    (path: '/foo', handler: Handler<Foo>) :void  
    (path: string, handler: Handler<any>):void;
}