The following code would produce the expected type error in Java, but TypeScript doesn't consider it an error. Is this by design, or is it a bug in 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)
In fact TypeScript doesn't even consider this an error:
const meters: Length = new Angle()
Does TypeScript treat all classes as structural instead of nominal types? I'm used to Java and Flow treating classes as nominal types.
Okay, my suspicion was correct, TypeScript currently treats classes as structural types but more support for nominal types is planned.
According to https://michalzalecki.com/nominal-typing-in-typescript/ one way to force TypeScript to treat a class like a nominal type is to use a private property:
However this still doesn't cause the desired errors above. I had to make sure that the type parameter for
Unit
is actually used to cause an error: