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>()
}

然而,这仍然不会导致上述所需的错误。我必须确保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"的参数。类型"Angle"不可分配给类型"Length"。类型具有私有属性"name"的单独声明。(2345(