typescript - TypeScript 泛型与 Java 有何不同?
问题描述
以下代码会在 Java 中产生预期的类型错误,但 TypeScript 并不认为这是错误。这是设计使然,还是 TypeScript 中的错误?
abstract class UnitType<T extends UnitType<T>> {
...
}
class Unit<T extends UnitType<T>> {
...
}
class Length extends UnitType<Length> {
static meters: Unit<Length> = new Unit<Length>()
}
class Angle extends UnitType<Angle> {
static degrees: Unit<Angle> = new Unit<Angle>()
}
class UnitizedNumber<T extends UnitType<T>> {
constructor(value: number, unit: Unit<T>) {
...
}
}
// Length and Angle are not compatible, so this should be an error.
const foo: UnitizedNumber<Length> = new UnitizedNumber<Length>(1, Angle.degrees)
事实上,TypeScript 甚至不认为这是一个错误:
const meters: Length = new Angle()
TypeScript 是否将所有类视为结构类型而不是名义类型?我习惯于 Java 和 Flow 将类视为名义类型。
解决方案
好吧,我的怀疑是正确的,TypeScript 目前将类视为结构类型,但计划对名义类型提供更多支持。
根据https://michalzalecki.com/nominal-typing-in-typescript/强制 TypeScript 将类视为名义类型的一种方法是使用私有属性:
class Length extends UnitType<Length> {
private __nominal: void
static meters: Unit<Length> = new Unit<Length>()
}
class Angle extends UnitType<Angle> {
private __nominal: void
static degrees: Unit<Angle> = new Unit<Angle>()
}
但是,这仍然不会导致上述所需的错误。我必须确保 type 参数Unit
实际上用于导致错误:
class Unit<T extends UnitType<T>> {
type: T
constructor(type: T) {
this.type = type
}
}
const foo: UnitizedNumber<Length> = new UnitizedNumber<Length>(1, Angle.degrees)
“Unit”类型的参数不能分配给“Unit”类型的参数。“角度”类型不能分配给“长度”类型。类型具有私有属性“名称”的单独声明。(2345)
推荐阅读
- godot - 无效的获取索引“get”(基于:“RigidBody2D (bird.gd)”)错误
- laravel - 无法在自定义服务中获取请求数据?
- javascript - 添加不重新定位页面的关闭功能
- java - Java 复制 ArrayList 值未参考
- laravel - Connect GIATA hotel mapping with postman
- asp.net - 如何使用 C# 在引导模式中添加/获取标签和文本框对
- linux - Where can I find the definition of the function PEM_read_bio_X509()?
- c# - Group by 子句不允许在类级别上分组
- makefile - makefile 模式匹配是否可以同时包含前缀和后缀作为变量?
- unity3d - 根据 Unity 中的另一个纹理更改纹理的颜色?