【问题标题】:Control flow analysis for Tuple Union Types元组联合类型的控制流分析
【发布时间】:2017-01-21 02:32:27
【问题描述】:

有没有办法告诉 typescript 元组的联合类型满足以下示例中任何代码路径的类型约束,而无需在函数体中手动指定每种情况?

type options = 
    [string, (a:string) => number]
    | [number, (b:number) => string ]

function f( [input,fn]: options) {
    // Error: Cannot invoke an expression which lacks a call signature
    return fn(input)
}

如果inputstring,那么fn 将接受string,如果inputnumberfn 将接受number。然而,Typescript 认为 fn 无法接受输入,因为它认为它是 string | number

可能的函数是(string) => number | (number) => string,其中输入是string | number。如果函数接受(string|number) => number | (string|number) => string 打字稿就可以了。但我想告诉 Typescript,fn 不可能不接受arg(这是真的)。​​

我理解为什么 Typescript 会确定各个类型不兼容。但我正在寻找一种方法来告诉 typescript 每个可能的元组都是自包含的,并且可以使用自己的函数调用自己的 arg。

【问题讨论】:

  • 对我来说似乎是正确的行为? f 接受一个元组,你想给它一个字符串还是一个数字?
  • 你的意思是递归调用,应该f(input) be fn(input)
  • 我认为他是的,因为最后一段提到 fn 而不是 f。这不是问题中的错字,因为他得到的错误是您调用f 时会得到的错误。我修改了我的答案以反映这一意图。由于一些相当复杂的类型理论,修复该错误仍然会失败。我想知道这是一个玩具示例,还是您真正想要使用的东西?
  • 这是我想用来键入调用 REST 端点可能接受的参数的东西。 @SimonMeskens

标签: typescript functional-programming tuples


【解决方案1】:

这是一种使其工作的类型安全方法。 as 关键字不是强制转换,如果类型不兼容,它抱怨。

type options = 
    [string, (a:string) => number]
    | [number, (b:number) => string ]

function f( [input,fn]: options) {
   return (fn as (a: string | number) => string | number)(input);
}

TypeScript 不够聪明,无法自己解决这个问题,因此需要通过稍微扩大类型来获得一些帮助。

【讨论】:

  • 是的,因为这是一个完全不同的例子。请注意,在原始问题中,他是递归调用,而不是调用回调。
  • 可能是他的错误,我会修改我的答案
  • 改写答案以适合问题
  • 我真的很想避免在函数体中枚举所有可能的类型。我想即使强制转换fn as any 也是类型安全的,因为它将在调用级别受到保护。这样就可以避免函数体中的枚举。
  • 它不会完全是类型安全的,但是是的,调用点应该是正确的类型安全的。
猜你喜欢
  • 2021-10-21
  • 2018-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-28
  • 2022-06-23
  • 2017-11-18
  • 1970-01-01
  • 2018-04-15
相关资源
最近更新 更多