打字稿:有效的逆变通用打字实际上是无效的

时间:2016-06-07 12:44:49

标签: generics types typescript

以下代码是完全有效的打字稿:

interface Promise<T> {
    then(resolved: (p: T) => number): number;
}

function as4(): Promise<{ x: number, y: number }> {
    let r: Promise<{ x: number }> = {
        then: resolved => resolved({ x: 4 })
    };
    return r;
}

function addAs4(): number {
    return as4().then(p => p.x + p.y);
}

使用异步承诺时,类似的代码非常常见。

但是,生成的javascript代码实际上已损坏,因为属性p.y不存在,因此添加会产生NaN

据我所知,typescript允许协变分配泛型类型以允许像

这样的代码
let common: Array<{ x: number }> = [];
let special: Array<{ x: number, y: number }> = [];

common = special;

所以我想,因为T中的类型参数Promise<T>仅出现在参数位置,它会切换为允许逆变分配。但是,T实际上并不作为then的参数出现,而是作为参数的参数,所以我希望它切换回协变分配(意味着resolved只能使用比{ x: number }更特殊的类型来调用。至少在我的例子中,这似乎是有意义的。有没有一个很好的理由为什么它没有?

此外,在使用promises时,这种行为会消除很多类型的安全性。有没有办法以某种方式告诉typescript编译器将泛型类型视为不变量(我认为在流程中你可以做这样的事情)?或者可能是另一种检测这类错误的解决方案?

0 个答案:

没有答案