为什么这两种类型的联合不在函数内部提供参数提示?

(ts playground)

type Valish = (value: string) => boolean
type CurryValish = (...args: number[]) => Valish

const check = {
  vin: (value) => true,            // ✗ any, should be string
  cin: (curry) => (value) => true, // ✗ any any, should ne number string
} satisfies {
  [key: string]: 
    | Valish
    | CurryValish
}

const checkValish = {
  vin: (value) => true,            // 🗸 string => boolean
} satisfies { [key: string]: Valish }

const checkCurry = {
  cin: (curry) => (value) => true, // 🗸 number => string => boolean
} satisfies { [key: string]: CurryValish }

它似乎足够好地理解上下文以提供大量信息,甚至在CurryValish类型的内部也是如此.那么,当替换为有效类型时,它为什么不提供参数类型呢?

const x: Valish | CurryValish = (a) => "hi"         
// Type 'string' is not assignable to type 'boolean | Valish'.(2322)

const y: Valish | CurryValish = (b) => (a) => "hi"
// Type '(a: any) => string' is not assignable to type 'boolean | Valish'.
//   Type '(a: any) => string' is not assignable to type 'Valish'.
//     Type 'string' is not assignable to type 'boolean'.

推荐答案

这是打印脚本的设计限制,如第microsoft/TypeScript#51639节所述.根据a comment by the language's architect:

只有当上下文函数类型具有相同的参数列表时,我们才能从上下文函数类型的联合中推断上下文参数类型,因此这实际上是一个设计限制.

因为ValishCurryValish没有相同的参数列表,所以不会发生contextual typing.


我想您希望编译器能够判断函数的return type,并使用它来区分联合.但这不会发生,特别是因为通常函数的返回类型取决于它的参数类型,因此编译器倾向于将这种推断推迟到它知道参数类型之后.这是一个循环,尽管可以很聪明地注意到,无论x是什么类型,x => true都会返回boolean,但这并不总是可以做到的.That的一般性问题是在microsoft/TypeScript#47599描述的(特别是在推断generic类型参数而不是区分联合的上下文中),通常这是一个困难的问题.

因此,即使类型脚本允许具有不同参数列表的函数的联合具有上下文参数类型,您也可能看不到您想要的行为.上面引用的 comments 的其余部分是:

在这种情况下,我们可以通过推断尽可能广泛的参数类型来做得更好.

这不会对unions 构成歧视 但是我们不能确定,直到或者除非函数的联合得到了上下文参数类型. 所以我在这里停止猜测.

Typescript相关问答推荐

如何准确确定此特定场景中的类型?

类型脚本:类型是通用的,只能索引以供阅读.(2862)"

为什么TypeScript假设文档对象始终可用?

我可以为情态车使用棱角形的路由守卫吗?

带下拉菜单的Angular 响应式选项卡

一个打字类型可以实现一个接口吗?

在另一个类型的函数中,编译器不会推断模板文字类型

如何在ANGLE中注册自定义验证器

如何缩小函数的返回类型?

如何从对象或类动态生成类型

TypeScrip-根据一个参数值验证另一个参数值

使用Type脚本更新对象属性

如何在Angular /字体中访问API响应的子元素?

为什么受歧视的unions 在一种情况下运作良好,但在另一种非常类似的情况下却不起作用?

打字:注解`是字符串`而不是`布尔`?

Typescript不允许在数组中使用联合类型

TypeScript中的这些条件类型映射方法之间有什么区别?

有没有一种简单的方法可以访问Keyboard Shortcuts JSON文件中列出的每个命令的显示名称(标题)?

Typescript 子类继承的方法允许参数中未定义的键

包含多个不同类构造函数的接口的正确类型?