【问题标题】:How are TypeScript generics different from Java?TypeScript 泛型与 Java 有何不同?
【发布时间】:2020-03-13 11:00:48
【问题描述】:

以下代码会在 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 generics type-parameter structural-typing nominal-typing


    【解决方案1】:

    好吧,我的怀疑是正确的,TypeScript 目前将类视为结构类型,但 more support for nominal types is planned

    根据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”类型的参数。 “角度”类型不能分配给“长度”类型。 类型具有私有属性“名称”的单独声明。 (2345)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-06
      • 2023-02-09
      • 1970-01-01
      • 2021-02-07
      • 2011-06-14
      • 2020-02-22
      • 2017-08-22
      • 2017-11-05
      相关资源
      最近更新 更多