【问题标题】:Why do only Functions with inline typing detect extra fields?为什么只有具有内联类型的函数才能检测到额外的字段?
【发布时间】:2020-06-17 12:13:39
【问题描述】:

我的印象是这些函数虽然以不同的方式编写,但具有完全相同的类型签名; 即

type Test = {
  a: number
}
type Fu = (a: number) => Test

var foo1: (a: number) => Test = a => ({ a }) // aka var foo1: Fu = a => ({ a })
var foo2 = (a: number): Test => ({ a })  

最近我发现其中一个允许传入额外的字段

var foo1: (a: number) => Test = a => ({ a, b:1}) // NO error!
var foo2 = (a: number): Test => ({ a, b:2 }) // 'b' does not exist 

这是为什么?这是 TS 的错误还是限制?

有时我无法内联输入函数(即泛型、覆盖、回调)是否有另一种方法来定义它们,使其始终像 foo2 一样?

playground link

【问题讨论】:

    标签: typescript typescript3.0


    【解决方案1】:

    Typescript 确实对对象字面量进行过多的属性检查,但仅当对象字面量用于指定其类型的上下文中时。当一个对象字面量出现在推断其类型的上下文中时,就没有指定的类型来检查它。

    在表达式(a: number): Test => ({a, b: 2}) 中,返回类型注释: Test 指定对象字面量应该是什么类型,因此Typescript 会进行多余的属性检查。

    在赋值var foo1: (a: number) => Test = a => ({a, b: 1}) 中,右侧是一个函数,其类型被推断为(a: number) => {a: number, b: number},这是一个完全合理的函数类型。函数本身没有类型注释,因此对象字面量用于推断函数的返回类型,而不是用于检查对象字面量的函数返回类型。然后没有错误,因为函数类型可以分配给foo1 的类型(因为函数类型的返回类型是协变的)。

    我不确定什么是合适的解决方法,但这就是为什么会发生这种情况的解释。

    【讨论】:

    • 并不是说我不欣赏您的回答(谢谢)我很想知道是否有解决方法。不知道github上有没有问题open?
    • 我认为,如果您将其作为问题发布,则很有可能将其关闭为“无法修复”或“按预期工作”,因为右侧的功能是可分配的到左边的类型。在您的用例中,该函数是否总是简单地返回一个对象文字而不做任何其他事情?
    • 是的,但是必须有一种方法可以在函数中将回调作为参数键入,这样它才能捕获额外的字段,不是吗?
    • 一种选择是编写一个像function test(t: Test): Test { return t; }这样的标识函数,然后箭头函数a => test({ a, b: 2 })将警告多余的属性,因为test函数正在根据参数类型检查对象文字Test.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-03
    • 2017-05-17
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 2011-05-07
    相关资源
    最近更新 更多