我有联合类型Item
和ItemSlot
,以及将Item
映射到Slot
的映射类型.
type WeaponSlot = "melee" | "ranged";
type ArmorSlot = "helmet" | "gloves" | "boots";
type Weapon = {
type: "weapon";
slot: WeaponSlot;
damage: number;
};
type Armor = {
type: "armor";
slot: ArmorSlot;
armorValue: number;
};
type Item = Weapon | Armor;
type ItemSlot = WeaponSlot | ArmorSlot;
// type ItemSlots = {
// melee: Weapon;
// ranged: Weapon;
// helmet: Armor;
// gloves: Armor;
// boots: Armor;
// }
type ItemSlots = {
[O in Item as O["slot"]]: O;
};
项目和项目槽之间有明确的关系,这在类型映射中得到了反映.但是我想不出如何利用这种关系,所以我可以创建一个可以得到Item
的泛型函数,并以一种类型安全的方式将它映射到正确的ItemSlot
.
这些都是有效的
// manual way
function putItem(item: Item, slots: ItemSlots) {
if (item.slot === "boots") {
slots["boots"] = item;
} else if (item.slot === "melee") {
slots["melee"] = item;
}
}
// can do generic when slot is passed from outside
function putItem2<S extends ItemSlot>(
item: ItemSlots[S],
slots: ItemSlots,
slot: S,
) {
slots[slot] = item;
}
但我不想要手动选项.并且插槽可能不会从外部传递,如下例所示
// a function that takes an item and puts it in its corresponding slot
function putItem3(item: Item, slots: ItemSlots) {
slots[item.slot] = item;
}
// or a function that takes an item list and slot as an input and
// filters items to get an item suitable for the slot
function putItem4(items: Item[], slot: ItemSlot, slots: ItemSlots) {
// just return the first item that suits to slot
const item = items.filter((item): item is Something => item.slot === slot)[0];
slots[item.slot] = item;
}
不知何故,我需要提示,该项目有一个插槽,将指向正确的插槽之一.我需要在Slot
上设置Item
通用吗?这将如何与unions 类型一起工作?或者,有没有更好的解决方案,也许不需要使用更多的泛型?
这似乎不是一个独一无二的问题.如果您能链接一些以泛型方式处理联合类型的自然示例,我也将不胜感激.