【问题标题】:Why are first class functions not type checked in typescript?为什么第一类函数没有在打字稿中进行类型检查?
【发布时间】:2017-01-17 02:51:48
【问题描述】:

在下面的示例中,Promise::then 访问者函数 f 期望收到 Example。如果我显式传入一个缺少属性的格式错误的对象,我会收到一个类型错误。

但是,如果我只是将函数 f 传递给 .then(f),则不会出现类型错误,即使 typescript 知道 Promise<T>T 的类型不是 Example

interface Example {
    id: number
    age: number
}

interface Promise <T> {
    then <U> ( f: ( a: T) => U ) : Promise<U> 
}

function f(s:Example){
    return s.age
}

var p : Promise<{ id: number }>

p.then(f) // no type error (bad)

p.then(function(a){
    f(a) // type error (good)
})

我想知道为什么会发生这种情况,还有在 Typescript 中减轻许可类型检查的技术。

如果双变量解释了这种现象,那么为什么在显式应用f 时会出现类型错误?为什么第一类函数与显式应用程序的规则不同?

【问题讨论】:

标签: generics typescript functional-programming


【解决方案1】:

这是我认为正在发生的事情:

p.then(f) // no type error (bad)
  • T 这里是{ id: number }
  • then() 被声明为采用 {id: number} =&gt; U 类型的参数
  • f 的类型为Example =&gt; number
  • Example 可分配给{id: number},因此fthen() 的参数类型兼容,因为bivariance

让我再举一个例子:

p.then(function(a : Example){
    f(a)
})

出于同样的原因,它也可以无错误地编译:

  • then() 的参数类型为 Example =&gt; number

现在,为什么下面的代码不能编译?

p.then(function(a){
    f(a) // type error (good)
})
  • 我猜a 被推断为具有{id: number} 类型(因为最简单的做法是从p 的声明中将其设为T
  • 所以f 在这里被调用,参数不兼容
  • 因为{id: number} 不能分配给Example 需要f(缺少年龄)。

请注意,错误不是关于 then() 的参数,而是关于 f() 的参数。

现在,问题的第二部分:

减轻 Typescript 中许可类型检查的技术。

如果您需要正确的类型检查,IMO Typescript 不是一个选项,只要不健全但“可用”的类型检查仍然是其明确的设计目标之一。我听说现在 Scala、Haskell 和 OCaml 都有针对 javacsript 的编译器(但我不知道它们的可用性如何)。

以及问题的第三部分:

为什么他们对一级函数和显式函数的规则不同 申请?

因为在第一种情况下,参数是一个函数,而在第二种情况下(不编译),参数推导出类型{id : number},它不是一个函数。双变量是一种临时规则,仅在需要确定一种函数类型是否与另一种函数类型兼容时才适用。第一个案例可以编译,因为一旦它看到 then() 参数根据规则是 OK 的,它就不会下降到 then() 实现以检查它在那里实际上是如何工作的。这就是它不健全的原因。

【讨论】:

  • 您的回答很有帮助,但我仍然不明白为什么二元对一等函数更宽松。如果双变量解释了这种现象,那么显式应用程序应该没有类型错误,同样的规则应该适用。当 Typescript 的泛型是一级函数时,问题是无法推断结构吗?
  • 我添加了答案的另一部分试图解释它。该错误是由不是函数的参数的参数类型不正确引起的,因此双变量不适用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-03
  • 2020-09-21
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
  • 2021-08-19
  • 1970-01-01
相关资源
最近更新 更多