Typescript ';CustomEnum.Case';可分配给类型为';T';,但是';T';可以使用约束的不同子类型';CustomEnum';
我正在定义一个接口,其中属性类型之一依赖于绑定到枚举的泛型参数p。我采用以下方法:Typescript ';CustomEnum.Case';可分配给类型为';T';,但是';T';可以使用约束的不同子类型';CustomEnum';,typescript,typescript-generics,Typescript,Typescript Generics,我正在定义一个接口,其中属性类型之一依赖于绑定到枚举的泛型参数p。我采用以下方法: export enum Scopes { Fruit = 'fruit', Vegetables = 'vegetables', } export enum FruitItemTypes { Strawberry = 'strawberry', Rasberry = 'rasberry' } export enum VegetableItemTypes { Potatoes = 'pota
export enum Scopes {
Fruit = 'fruit',
Vegetables = 'vegetables',
}
export enum FruitItemTypes {
Strawberry = 'strawberry',
Rasberry = 'rasberry'
}
export enum VegetableItemTypes {
Potatoes = 'potatoes',
Carrots = 'currency',
}
export type ItemTypes = FruitItemTypes | VegetableItemTypes
interface ItemTypeForScope {
[Scopes.Fruit]: FruitItemTypes;
[Scopes.Vegetables]: VegetableItemTypes;
}
export interface Item {
id: string;
type: ItemTypes;
}
export interface ScopedItem<T extends Scopes> extends Item {
type: ItemTypeForScope[T];
}
export interface ScopedData<T extends Scopes> {
items: ScopedItem<T>[];
}
export type Data = { [scope in Scopes]: ScopedData<scope> };
导出枚举作用域{
水果=‘水果’,
蔬菜=‘蔬菜’,
}
导出枚举类型{
草莓=‘草莓’,
拉斯贝里=‘拉斯贝里’
}
导出枚举VegetableItemTypes{
土豆=‘土豆’,
胡萝卜=‘货币’,
}
导出类型ItemTypes=FruitItemTypes | VegetableItemTypes
接口项类型示波器{
[范围.水果]:水果类型;
[范围.蔬菜]:VegetableItemTypes;
}
导出接口项{
id:字符串;
类型:项目类型;
}
导出接口ScopedItem扩展项{
类型:ItemTypeForScope[T];
}
导出接口范围数据{
项目:ScopedItem[];
}
导出类型数据={[Scopes中的scope]:ScopedData};
我还想使用ScopedItem
作为以下函数的返回类型:
const getItemType = <T extends Scopes>(data: Data, scope: T): ScopedItem<T>[] => {
return data[scope].items
}
const getItemType=(数据:数据,作用域:T):ScopedItem[]=>{
返回数据[scope]。项
}
然而,我得到了以下错误,但据我所知,泛型参数T最终将是enum案例之一
Type 'ScopedItem<Scopes.Fruit>[] | ScopedItem<Scopes.Vegetables>[]' is not assignable to type 'ScopedItem<T>[]'.
Type 'ScopedItem<Scopes.Fruit>[]' is not assignable to type 'ScopedItem<T>[]'.
Type 'ScopedItem<Scopes.Fruit>' is not assignable to type 'ScopedItem<T>'.
Type 'Scopes.Fruit' is not assignable to type 'T'.
'Scopes.Fruit' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Scopes'.
Type'ScopedItem[]| ScopedItem[]不可分配给Type'ScopedItem[]。
类型“ScopedItem[]”不可分配给类型“ScopedItem[]”。
类型“ScopedItem”不可分配给类型“ScopedItem”。
类型“Scopes.Fruit”不可分配给类型“T”。
“Scopes.Fruit”可分配给“T”类型的约束,但“T”可以用约束“Scopes”的不同子类型实例化。
我相信这里的问题与。。。您希望编译器将
{[K in Scopes]:ScopedData}[P]
计算为类似ScopedData[P]
的值,其中P
是扩展K
的泛型类型参数。但编译器不会进行这种高阶推理,即在解析泛型类型之前对具体类型的泛型函数进行相似化;在某些情况下,有一种方法可以实现这一点,但在TS3.5中就没有了
所以,解决办法。。。编译器可以验证以下内容:
const getItemType = <T extends Scopes>(
data: Data,
scope: T
): Data[T]["items"] => {
return data[scope].items;
};
const getItemType=(
数据:数据,
经营范围:T
):数据[T][“项目”]=>{
返回数据[范围]。项;
};
将data[scope].items的类型作为ScopedItem[]
返回,而不是将其作为data[T][“items”]
返回。这些结果将是相同的,当您实际调用具体类型的scope
参数上的getItemType()
时,它将以相同的具体类型结束
或者,您可以承认您的推理能力优于编译器的推理能力,并使用a让编译器知道谁是老板:
const getItemTypeAssertion=(
数据:数据,
经营范围:T
):ScopedItem[]=>{
返回(数据[范围]作为ScopedData).items;//关于你的游乐场链接,我比编译器更聪明……这些不是并集和交集。你使用的是非常不同的。x | | y
和x&&y
将根据x
的真实性/错误性,始终计算为x
或y
中的一个。谢谢你的详细解答r和问题参考,我相信Data[T][“items”]
与编译器推断的类型相同。在这种情况下,类型断言似乎是一个很好的解决方案。关于逻辑运算符,这是一个漫长的一天,但感谢您在本例中对其无关性的反馈:)非常详细地介绍了此错误消息。请看一看。