1

这对我来说很常见,但我并没有偶然发现简单的解决方案。

我有以下枚举(每个枚举都有更多值,但为了简单起见,我将它们缩减为两个。另请注意,每个枚举中的相同枚举键和值只是修剪的结果,而不是特定情况) :

enum CampPersons {
    HEALER = 'healer',
    MERCHANT = 'merchant',
    TUTOR = 'tutor',
}
enum HealerUpgrades {
    UNLOCK = 'unlock',
    TRAVEL = 'travel',
}

enum MerchantUpgrades {
    UNLOCK = 'unlock',
    TRAVEL = 'travel',
}

enum TutorUpgrades {
    UNLOCK = 'unlock',
}

export type CampPersonUpgrades = HealerUpgrades | MerchantUpgrades | TutorUpgrades;

然后我有使用这些枚举的对象,如下所示:

export const CampPersonUpgradesIcons = {
    [CampPersons.HEALER]: {
        [HealerUpgrades.UNLOCK]: HealIcon,
        [HealerUpgrades.TRAVEL]: TravelIcon,
    },
    [CampPersons.MERCHANT]: {
        [MerchantUpgrades.UNLOCK]: GoldIcon,
        [MerchantUpgrades.TRAVEL]: TravelIcon,
    },
    [CampPersons.TUTOR]: {
        [TutorUpgrades.UNLOCK]: BookIcon,
    },
};

当我尝试访问适当的图标进行人员升级时出现问题

const person: CampPersons = ...;
const upgrade: CampPersonUpgrades = ...;

const icon = CampPersonUpgradesIcons[person][upgrade];

显然打字稿编译器无法确定upgrade用于访问特定图标是否正确,CampPersonUpgradesIcons[person]因为它可以是HealerUpgradesMerchantUpgradesTutorUpgrades

显然,对于人类(不是打字稿)来说,什么时候person是从. 我的问题是告诉打字稿编译器for将匹配适当的枚举的最简单方法是什么(不使用像or之类的条件类型)。CampPersons.HEALERupgradeHealerUpgradesupgradepersonupgrade extends HealerUpgrades ? HealerUpgrades : ...//@ts-ignore

编辑:我在我的 React 组件中使用了@jcalz 答案,但不幸的是我在这个操场上遇到了进一步的问题

4

1 回答 1

0

正如您所注意到的,您不能只说那person是类型CampPersons,那 upgrade是类型CampPersonUpgrades,并期望编译器了解它们之间的关系。您可能希望图标索引代码在 的类型中是通用person的,如下所示:

function getIcon<P extends CampPersons>(
  person: P, upgrade: keyof typeof CampPersonUpgradesIcons[P]) {
  return CampPersonUpgradesIcons[person][upgrade]; // okay
}

这里person现在是泛型类型P,它被限制为CampPersons,并且 的类型与upgrade显式相关P。这为您提供了以下行为:

const healerUnlockIcon = getIcon(CampPersons.HEALER, HealerUpgrades.UNLOCK); // okay
const oopsIcon = getIcon(CampPersons.MERCHANT, TutorUpgrades.UNLOCK); // error!
// ------------------------------------------> ~~~~~~~~~~~~~~~~~~~~
// 'TutorUpgrades' is not assignable to 'MerchantUpgrades'

这是否满足您的需求或至少给您一些方向?祝你好运!

Playground 代码链接

于 2020-01-05T01:02:01.247 回答