TypeScript:子类型化和协变参数类型 [英] TypeScript: subtyping and covariant argument types

查看:127
本文介绍了TypeScript:子类型化和协变参数类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

常识表明,子类型在返回类型方面应该是协变的,而在参数类型方面应该是相反的。因此,由于 Ef 的严格协变参数类型,以下内容应被拒绝:

Common sense suggests that subtyping should be covariant with respect to return type but contravariant with respect to argument types. So, the following should be rejected, because of the strictly covariant argument type of E.f:

interface C {
   f (o: C): void
}

interface D extends C {
   g (): void // give D an extra service
}

class E implements C {
   // implement f with a version which makes stronger assumptions
   f (o: D): void {
      o.g() // rely on the extra service promised by D
   }
}

// E doesn't provide the service required, but E.f will accept
// an E argument as long as I invoke it via C.
var c: C = new E()
console.log('Try this: ' + c.f(c))

确实,正在运行程序打印

Indeed, running the program prints

Uncaught TypeError: o.g is not a function

所以:(1)什么是这里的基本原理(大概有一个,但是不令人满意,并且很JavaScript); (2)在这种情况下,编译器是否有任何实际原因不能忽略警告?

So: (1) what's the rationale here (presumably there is one, however unsatisfying and JavaScripty); and (2) is there any practical reason why the compiler can't omit a warning in this situation?

推荐答案

按照<上面的href = https://stackoverflow.com/users/6309244/krontogiannis> krontogiannis '注释,在比较函数类型时,一个可以是另一个 的子类型,因为源参数类型可分配给相应的目标参数类型,因为相应的目标参数类型可分配给源参数类型。在语言规范中,这称为函数参数二元变量

As per krontogiannis' comment above, when comparing function types, one can be a subtype of the other either because a source parameter type is assignable to the corresponding target parameter type, or because the corresponding target parameter type is assignable to the source parameter type. In the language specification this is called function parameter bivariance.

允许双变量参数类型的原因与可变性的天真期望相反,是因为对象是可变的。在纯语言中,逆协是唯一明智的选择,但是对于可变对象,协变还是协变是否有意义取决于您是在读取结构还是在结构中读写。由于无法(目前)在类型系统中表达这种区别,因此双方差是一种合理的(尽管不合理的)折衷方案。

The reason for permitting bivariant argument types, as opposed to the "naive" expectation of contravariance, is that objects are mutable. In a pure language contravariance is the only sane option, but with mutable objects whether covariance or contravariance makes sense depends on whether you're reading from or writing to the structure. Since there's no way (currently) to express this distinction in the type system, bivariance is a reasonable (albeit unsound) compromise.

这篇关于TypeScript:子类型化和协变参数类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆