【问题标题】:wrong type inference with generics泛型的错误类型推断
【发布时间】:2014-06-21 20:34:34
【问题描述】:

下面的代码中有很多行文本的错误。当我将箭头标记行中泛型的Y参数更改为数字或字符串等类型时,一切正常,编译后没有错误

问题 1 - 它是编译器错误吗? 问题 2 - 如何修复错误?

class channel<S,Y>{

public merge(...channels:channel<any, Y>[]) {

    var ch = new channel<void, channel<any, Y>>(); // <---

    var result = ch.flatMap(x => x);

    return result;
}

public flatMap<R>(projector: (data: Y) => channel<any, R>): channel<Y, R> {
    return null;
}
}

预期的结果类型是channel&lt;any, Y&gt;,但编译器会推断出不同的结果

错误信息:

Error   1   Supplied parameters do not match any signature of call target:
Call signatures of types '(x: channel<any, channel<any, Y>>) => channel<any, channel<any, Y>>' and 
                         '(data: channel<any, channel<any, Y>>) => channel<any, Y>' are incompatible:
    Types 'channel<any, channel<any, Y>>' and 'channel<any, Y>' originating in infinitely expanding type reference have incompatible type arguments.    

更新

public flatMap<R>(projector: (data: Y) => channel<any, R>): channel<any, R> {} // changed Y to any

public correct(...targets: channel<any, Y>[]) {
    var ch = new channel<void, channel<any, Number>>().named('merge');

    var result = ch.flatMap(x => x);


    return result;
}     

public incorrect(...targets: channel<any, Y>[]) {
    var ch = new channel<void, channel<any, Y>>().named('merge'); // changed Number to Y

    var result = ch.flatMap(x => x); // error


    return result;
}     

那里有一些魔法。当我这样改变时,我得到了 (x:Number):Number =&gt; x 。但是当使用 Y 时,x 是channel&lt;any, channel&lt;any,Y&gt; &gt;

【问题讨论】:

  • named的定义是什么?
  • 我是public named(name: string) {/*skip*/ return this; }
  • 确实,我犯了一个错误。我解决了一些问题,但主要问题仍然存在
  • 创建了具有正确描述的新线程stackoverflow.com/questions/23478801/…

标签: types typescript


【解决方案1】:

预期的结果类型是channel&lt;any, Y&gt;

我不明白你是如何得出这个结论的。按照这个类和函数的定义:

  1. ch 的类型是channel&lt;void, channel&lt;any, Y&gt;&gt;(明确给出)
    • ch#S = void
    • ch#Y = channel&lt;any, Y&gt;
  2. flatMap&lt;R&gt;channel&lt;S, Y&gt; 上调用时返回 channel&lt;Y, R&gt;(明确给出)
  3. 对于ch.flatMap 的调用,Y = channel&lt;any, Y&gt;(来自 1.b)
  4. 因此返回类型为channel&lt;channel&lt;any, Y&gt;, R&gt;(替换为2中定义的Y

无论如何,因为你有一个无限扩展的泛型类型(参见 TypeScript 规范第 3.8.7 节),泛型类型推断必然会受到限制(我相信这个问题实际上是无法确定的)。在这种情况下,最好的办法是手动指定类型参数,或者通过为 x 提供类型注释来给编译器一个额外的提示。

【讨论】:

  • 当我将 Y 参数更改为数字时,一切正常。我想这意味着编译器由于错误而无法推断类型
  • 我不知道应该给出哪个注释,因为除了 之外的所有注释都不起作用
  • 当您将Y 更改为number 时,它变为channel&lt;channel&lt;any, channel&lt;any, Y&gt;&gt;, Y&gt;,而不是“预期”的channel&lt;any, number&gt;
  • 确实,同意。但是请看我第一条消息中的更新部分。
【解决方案2】:

这可能是类型推断的错误,也可能不是。这是一个复杂的例子,所以也许无法推断出泛型类型是有原因的。您可以通过在调用 flatMap&lt;R&gt;() 时指定 R 来帮助它

var result = ch.flatMap<channel<any, Y>>(x => x);

或通过完全限定 lambda

var result = ch.flatMap((x: channel<void, channel<any, Y>>): channel<void, channel<any, Y>> => {
    return x;
});

我觉得第一个看起来好多了。

【讨论】:

  • 您的选项都没有给出预期的结果类型。预期结果是 channel.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多