TypeScript 注解参数不用于推断剩余参数,

1qczuiv0  于 7个月前  发布在  TypeScript
关注(0)|答案(2)|浏览(62)

🔎 搜索词

带注解的,“rest参数”

🕗 版本与回归信息

  • 我尝试的每个版本都有这种行为

⏯ Playground链接

https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABAWwNYEFrzAHgJJgAOIUiApgB5RlgAmAzogIZgCeA2gLoB8AFE1gQAuRAG8AUIimJgARiG8AdMor0hBYlACUiALzdEANzgxaAGknTgAJgXLFq9URI79Rk+fEBfHaK-jxNExYBF4JaRlZXgoheigAJxgwAHMzRFYhMBBkACMyeN8vC0spG2i01kKLCIB6GsQKZjp05niyRCTgfLbaZkYAIhZWfurpOvJDGkQoAAs4EGSZmWsOxk7usl6mAeiROMSUipEs3PzXA2NTfu8tAG5xIA

💻 代码

function mkAction<Input extends any[]>(action: {
    f1:(...xs:Input) => void,
    f2:(...xs:Input) => void,
}) {}

mkAction({
    f1(x:string, y:number) {},

    f2(x, y) {},
    // x and y are inferred as "any",
    // even though f2 is inferred as "(x: string, y: number) => void"
});

🙁 实际行为

参数 "x" 和 "y" 被推断为 "any",尽管 "f2" 具有正确的类型 (x: string, y: number) => void

🙂 预期行为

我希望对 "f2" 的参数进行 x: stringy: number 的推断。

关于问题的附加信息

  • 无响应*
6bc51xsx

6bc51xsx2#

这是一个有趣的问题。inferFromAnnotatedParameters 的确不会从剩余参数中推断,它也不会尝试将推断结果与上下文中的剩余参数统一。第一个问题体现在另一个问题上:

function mkAction2<Input extends any[]>(action: {
  f1: (...xs: Input) => void;
  f2: (...xs: Input) => void;
}) {}

mkAction2({
  f1(...rest: string[]) {},
  f2(...rest) {
    rest;
    // ^? (parameter) rest: any[]
  },
});

这个问题似乎是一个相对容易解决的问题,我在这里没有看到额外的考虑因素。
第二个问题(与 OP 的问题相关)也不太难在这里实现。然而,这个问题有一些额外的考虑因素。剩余参数的问题在于我们不知道它实际上可能有多少个项目。据我所知,对于这种推断出的元组,没有统一算法。

function mkAction3<Input extends any[]>(action: {
  f1: (...xs: Input) => void;
  f2?: (...xs: Input) => void;
  f3?: (...xs: Input) => void;
}) {}

mkAction3({
  f1(x: string, y: number) {},
  f2(x: string, y: number, z: string) {},
  f3(x, y, z) {},
});

如果能推断出 [x: string, y: number, z: string] 就好了,但它首先推断出了 [x: string, y: number] ,然后推断出了第二个 [x: string, y: number, z: string] 候选项。当它有两个这样的候选项时,它会选择第一个。这样一来,它就无法通过签名适用性检查,因为在示例化后,事实证明 f2 应该为 (x: string, y: number) => void ,但提供的参数需要多一个参数。
这里还有一个额外的错误...当悬停在 mkAction3 调用上时,我们可以看到错误的签名:

function mkAction3<any[]>(action: {
    f1: (...xs: any[]) => void;
    f2?: ((...xs: any[]) => void) | undefined;
    f3?: ((...xs: any[]) => void) | undefined;
}): void

这个类型参数没有被推断为 any[] - 它被推断为 [x: string, y: number] 。如果我们手动提供 any[] ,这个调用将会成功。
另一方面...关于不同形状的元组,这是目前已经实现的功能,所以我不确定担心这个问题是否合理。
另一个有趣的事情是,在原始问题中,上下文签名有一个剩余参数。在这种情况下,使用非固定推理Map器示例化上下文签名。这与上下文签名没有剩余参数的情况不同,因为在那种情况下,使用固定推理Map器。它们之间有一个重要的区别,固定的Map器可以使用 inferFromIntraExpressionSites ,而非固定的Map器不能。
此对象中的前一个方法就是这样的一个表达式内部推理站点,如果那个非固定Map器或者我们在示例化该上下文签名时切换到固定Map器使用它,那么这也会正确地推断出来。从这些内部表达式站点进行推断绝对是为了修复推理的,因此将其包含在非固定Map器中是不正确的。我不知道如果只是切换到使用固定Map器会发生什么问题,但这里的区分必须存在,代码的结构使得这绝对不是误操作。
无论如何,我可能会对 inferFromAnnotatedParameters 进行更改,然后尝试探索如何统一从剩余参数中进行的逆变推理。

相关问题