typescript键和字符串的通用约束:ts2322
我正在尝试编写一个泛型类,它保留一对指向泛型类型键的特殊指针。下面是这个MVP的一个例子typescript键和字符串的通用约束:ts2322,typescript,typescript-generics,Typescript,Typescript Generics,我正在尝试编写一个泛型类,它保留一对指向泛型类型键的特殊指针。下面是这个MVP的一个例子 const _idKey = Symbol('_idKey') const _sortKey = Symbol('_sortKey') export interface BaseStoreConfig<T, Tid extends keyof T, Tsk extends keyof T | undefined> { idKey?: Tid sortKey?: Tsk } expor
const _idKey = Symbol('_idKey')
const _sortKey = Symbol('_sortKey')
export interface BaseStoreConfig<T, Tid extends keyof T, Tsk extends keyof T | undefined> {
idKey?: Tid
sortKey?: Tsk
}
export class BaseStore<T, Tid extends keyof T & string, Tsk extends keyof T | undefined> {
public [_idKey]: keyof T | 'id'
public [_sortKey]?: keyof T | undefined
constructor({
idKey = 'id', // Errors, see below
sortKey,
}: BaseStoreConfig<T, Tid, Tsk>) {
this[_idKey] = idKey
this[_sortKey] = sortKey
}
}
我通常理解这个错误,但在这种情况下我感到困惑。
string
的子类型如何不能分配给此类型?有什么方法可以表达这个约束吗?我认为问题在于,Typescript实际上不支持相同值的不同类型(例如,idKey
),这取决于该值是从调用者一侧(Tid
或未定义的
)还是从实现者一侧(Tid
或“id”)查看的
)。也有类似的问题,比如归档为bug,但我不确定它们何时会得到解决
您已将构造函数参数注释为类型BaseStoreConfig
,其idKey
属性的类型为Tid |未定义的。在尝试将默认值“id”
分配给它时,编译器将其视为不匹配。。。因为“id”
可能无法分配给Tid
。提到string
而不是特别提到“id”
的特定错误似乎是3.9之后对TypeScript的一些更改(不确定原因,但我假设它在其他地方做了合理的事情)。如果恢复到3.9,您将看到显式提到“id”
的错误
因此,我认为这里的解决办法是不要在分解结构中使用默认值,因为没有很好的方法来表示相同值的两种不同类型。相反,我们只需将默认值移动到构造函数的主体:
constructor({
idKey, sortKey,
}: BaseStoreConfig<T, Tid, Tsk>) {
this[_idKey] = idKey ?? "id" // okay
this[_sortKey] = sortKey
}
构造函数({
idKey,sortKey,
}:BaseStoreConfig){
这个[_idKey]=idKey???“id”//好的
这个[\u sortKey]=sortKey
}
现在所有的东西都编译好了,没有错误
我认为问题在于,Typescript并不真正支持相同值的不同类型(例如,idKey
),这取决于该值是从调用者一侧(Tid
或undefined
)还是从实现者一侧(Tid
或“id”
)查看的。也有类似的问题,比如归档为bug,但我不确定它们何时会得到解决
您已将构造函数参数注释为类型BaseStoreConfig
,其idKey
属性的类型为Tid |未定义的。在尝试将默认值“id”
分配给它时,编译器将其视为不匹配。。。因为“id”
可能无法分配给Tid
。提到string
而不是特别提到“id”
的特定错误似乎是3.9之后对TypeScript的一些更改(不确定原因,但我假设它在其他地方做了合理的事情)。如果恢复到3.9,您将看到显式提到“id”
的错误
因此,我认为这里的解决办法是不要在分解结构中使用默认值,因为没有很好的方法来表示相同值的两种不同类型。相反,我们只需将默认值移动到构造函数的主体:
constructor({
idKey, sortKey,
}: BaseStoreConfig<T, Tid, Tsk>) {
this[_idKey] = idKey ?? "id" // okay
this[_sortKey] = sortKey
}
构造函数({
idKey,sortKey,
}:BaseStoreConfig){
这个[_idKey]=idKey???“id”//好的
这个[\u sortKey]=sortKey
}
现在所有的东西都编译好了,没有错误
考虑const z:'foo'和string='id'代码>-这将不起作用,因为“id”不可分配给“foo”,因此,如果您使用“id”以外的键传入一些t,您在这里也会遇到同样的问题。至于“有没有办法表达这个约束?”——不是100%确定你在这里要做什么。我认为您使用“id”作为默认键的设计要点,而不对T的形状进行假设,会导致打字混乱。也许你可以添加一些用法的例子,什么应该起作用,什么不应该起作用等等,我可以帮助你,我不完全理解Tid
需要是T
的一个键,因此T
不能是'foo'
,或者Tid
没有可能的类型。不是使用<代码>键<代码>强制<代码> t>代码>作为对象吗?考虑<代码> const z:'fo'和string=id;<代码>-这将不起作用,因为“id”不可分配给“foo”,因此,如果您使用“id”以外的键传入一些t,您在这里也会遇到同样的问题。至于“有没有办法表达这个约束?”——不是100%确定你在这里要做什么。我认为您使用“id”作为默认键的设计要点,而不对T的形状进行假设,会导致打字混乱。也许你可以添加一些用法的例子,什么应该起作用,什么不应该起作用等等,我可以帮助你,我不完全理解Tid
需要是T
的一个键,因此T
不能是'foo'
,或者Tid
没有可能的类型。使用keyof
是否强制t
成为对象?