2016-09-09 65 views
2

在下面的示例中,Promise::then访问者函数f有望收到Example。如果我显式传递一个缺少属性的格式错误的对象,我会得到一个类型错误。为什么没有在打字稿中检查头等功能?

但如果我只是传递函数f.then(f)我没有得到任何类型的错误,即使打字稿知道在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时为什么会出现类型错误?为什么他们的第一类函数与显式应用程序有不同的规则?

+0

可能的重复:http://stackoverflow.com/questions/38699449/compatible-types-in-functions/38700451#38700451。另请参见[类型检查不稳定性:在TypeScript团队/社区中标准化处理此类问题](https://github.com/Microsoft/TypeScript/issues/9825) – artem

+0

@artem我不认为这是由于双变量。但我可能是错的。 –

回答

2

这里是什么,我认为正在发生的事情:

p.then(f) // no type error (bad) 
  • T这里是{ id: number }
  • then()声明采取型{id: number} => U
  • f的的参数类型Example => number
  • Example是分配给{id: number},所以f与参数类型的then()由于bivariance

兼容让我再补充一个例子:

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

它还编译没有错误,出于同样的原因:

  • 论据then()的类型为Example => number

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

p.then(function(a){ 
    f(a) // type error (good) 
}) 
  • 我想这a被推断为有型{id: number}(因为这样做最简单的事情就是要把它是Tp声明)
  • 所以f被称为与此处不兼容的参数
  • 因为{id: number}不能转让给Examplef需要(年龄是missin G)。

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

现在,对于问题的第二部分:

技术来减轻许可类型中打字稿检查。

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

而问题的第三部分:

为什么是一等功能VS明确 应用各自不同的规则?

因为在第一种情况下的参数是一个函数,和在第二种情况下(其不编译)参数已经推导出类型{id : number},这是不是一个函数。双变量是一个临时规则,仅当需要确定一个函数类型是否与另一个函数类型兼容时才适用。第一种情况编译,因为一旦它看到根据规则then()参数是好的,它不会下降到then()实现来检查它将如何在那里实际工作。这是什么使它不健全。

+0

您的回答很有帮助,但我仍不明白为什么双差异更适合第一类功能。如果双变量解释了这种现象,那么对于显式应用程序应该没有类型错误,应该应用相同的规则。 问题Typescript的泛型在第一类函数中无法推断结构吗? –

+0

我添加了另一部分答案试图解释它。错误是由不正确的参数类型引起的,因为参数不是函数,所以双变量不适用。 – artem