以下代码是完全有效的打字稿:
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编译器将泛型类型视为不变量(我认为在流程中你可以做这样的事情)?或者可能是另一种检测这类错误的解决方案?