【问题标题】:typescript : generic type with primitive types constraintypescript :具有原始类型约束的泛型类型
【发布时间】:2018-03-05 08:33:32
【问题描述】:

我在打字稿中有以下通用类

type UserId = number
type Primitive = string | number | boolean
class ColumnValue<T, S extends Primitive> {
    constructor(public columnName: String, public value: S) { }
}
abstract class Column<T> {
    constructor(public columnName: String) { }
    public set<S extends Primitive>(value: T): ColumnValue<T, S> {
        return new ColumnValue(this.columnName, this.getValue(value))
    }
    public abstract getValue<S extends Primitive>(value: T): S
}
let id = new class extends Column<UserId> {
    constructor() { super("id") }
    public getValue(value: UserId): number {
        return value
    }
}()

但我不知道为什么会出现此错误 类“(匿名类)”错误地扩展了基类“列”。 属性“getValue”的类型不兼容。 类型 '(value: number) => number' 不可分配给类型 '(value: number) => S'。 类型“数字”不可分配给类型“S”

【问题讨论】:

  • 可能你必须以具体的方式定义 S。 S 扩展了布尔值,但它到底是什么?
  • @jaibatrik 我编辑了我的问题,也许现在更清楚了,我希望 ts 编译器推断 ColumnValue 类 中的值类型并确保它是 Primative 类型

标签: typescript typescript-generics


【解决方案1】:

Column 上,getter 和 setter S 不一定是同一类型,因此您应该将类​​型参数移至其父类:Column&lt;T, S extends Primitive&gt;

type UserId = number
type Primitive = string | number | boolean
class ColumnValue<T, S extends Primitive> {
    constructor(public columnName: String, public value: S) { }
}
abstract class Column<T, S extends Primitive> {
    constructor(public columnName: String) { }
    public set(value: T): ColumnValue<T, S> {
        return new ColumnValue(this.columnName, this.getValue(value))
    }
    public abstract getValue(value: T): S
}
let id = new class extends Column<UserId, number> {
    constructor() { super("id") }
    public getValue(value: UserId): number {
        return value
    }
}()

至少has no errors以上的版本。

我知道您可能想从您与 setter 一起使用的任何类型中推断出 S,但 Column 在实例化时必须具有明确定义的类型,这意味着您在调用构造函数时要么显式(即new Column&lt;UserId, number&gt;(...)) 或在构造函数中添加 S 参数,以便可以从中推断出 S(如在 new Column&lt;UserId&gt;('id', 123) 中)

【讨论】:

  • 谢谢,但是是编译器错误,还是infer有逻辑意义S
【解决方案2】:

您的getValue 使用通用S,因此,继承的实现也必须使用S

let id = new class extends Column<UserId> {
    constructor() { super("id") }
    public getValue<S extends Primative>(value: UserId): S {
        return <S>value
    }
}()

如果你把S带到课堂上,你的功能可以缩小到number

abstract class Column<T, S extends Primative> {
    constructor(public columnName: String) { }
    public set(value: T): ColumnValue<T, S> {
        return new ColumnValue(this.columnName, this.getValue(value))
    }
    public abstract getValue(value: T): S
}

let id = new class extends Column<UserId, UserId> {
    constructor() { super("id") }
    public getValue(value: UserId): number {
        return value
    }
}()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 2020-05-30
    • 1970-01-01
    • 2014-05-07
    • 1970-01-01
    • 2017-01-21
    相关资源
    最近更新 更多