Typescript回调参数签名打破了打字

时间:2018-03-04 18:57:42

标签: typescript

所以使用@next版本的Typescript

可以很好地工作
function fork<
  Paths extends Partial<Paths>,
  OutputType extends keyof Paths
> (callback: () => OutputType, paths: Paths) {
  const result = callback()
  const path: () =>  ReturnType<Paths[OutputType]> = paths[result]
  const pathResult = path()

  return pathResult
}

const myResult = fork(() => 'bar', {
  foo: () => 'bip',
  bar: () => 123
})

根据返回的第一个回调字符串, myResult 输入正确。

然而,当我做这个小小的改变时:

function fork<
  Paths extends Partial<Paths>,
  OutputType extends keyof Paths
> (callback: () => OutputType, paths: Paths) {
  const result = callback()
  const path: (p: string) =>  ReturnType<Paths[OutputType]> = paths[result]
  const pathResult = path('foo')

  return pathResult
}

const bah = fork(() => 'bar', {
  foo: (p) => 'bip',
  bar: (p) => 123
})

基本上只是添加一个参数,整个事情就没有好的错误信息。

要看这个,只需使用最新的2.8(@next)版本的Typescript将代码粘贴到VS Code中。

1 个答案:

答案 0 :(得分:2)

我认为你可能会在&#34;隐含any&#34;中遇到一些怪癖。键入函数参数。我几乎总是使用--noImplicitAny编译器选项,当我在这里为参数提供显式类型注释时,你的错误似乎消失了:

const bah = fork(() => 'bar', {
  foo: (p: any) => 'bip',
  bar: (p: any) => 123
})

话虽如此,您使用的类型参数限制是奇怪的。我不知道Paths extends Partial<Paths>应该达到的目标。就个人而言,我倾向于像这样输入你的功能:

function fork<T, K extends keyof T>(
  callback: () => K, 
  paths: {[P in keyof T]: (p: string)=>T[P]} 
): T[K] {
  const result = callback()
  const path = paths[result];
  const pathResult = path('foo')
  return pathResult
}

使用inference from mapped types代替predefined conditional type ReturnType<>。使用条件类型并没有什么问题,但由于它们没有正式可用,我不知道它是否足够稳定可以使用。但无论如何,您应该以一种让TypeScript知道它们应该具有属性的方式来定义paths的类型。

希望这很有用。祝好运!