打字稿:具有原始类型约束的泛型类型
我在打字稿中有以下泛型类
I have the following generic classes in typescript
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
}
}()
但我不知道为什么会出现此错误 Class '(Anonymous class)' 错误地扩展了基类 'Column'.属性getValue"的类型不兼容.类型 '(value: number) => number' 不能分配给类型 '(value: number) => S'.数字"类型不能分配给S"类型
but I don't know why get this error Class '(Anonymous class)' incorrectly extends base class 'Column'. Types of property 'getValue' are incompatible. Type '(value: number) => number' is not assignable to type '(value: number) => S'. Type 'number' is not assignable to type 'S'
On Column
getter 和 setter S
不一定是相同的类型,所以你应该移动类型其父类的参数:Column
.
On Column
getter and setter S
isn't necessarily the same type so you should move the type param to its parent class: Column<T, S extends Primitive>
.
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
}
}()
以上版本至少没有错误.
我知道您可能想从与 setter 一起使用的任何类型推断 S
,但 Column
在实例化时必须具有明确定义的类型,因此这意味着您要么在调用构造函数时显式(即 new Column
),要么在构造函数中添加一个 S
参数,以便 S
可以从中推断出来(如 new Column
)
I understand that you probably want to infer the S
from whatever type you use with you setter but Column
must have a well defined type upon instantiation, so that means that you either explicit when calling the constructor (that is new Column<UserId, number>(...)
) or add a S
param in the constructor so S
can be inferred from it (like in new Column<UserId>('id', 123)
)