How would one model some types hierarchy in TypeScript that would enforce a limited amount of values to a key inside an object based on the value of another key in the same object?
Example:
Imagine you are tracking all the possible EntryPoints and Triggers that allow a user to see a certain component. For simplicity let's say the component is a Modal in your webpage.
These are the possible values, but not all combinations of them are possible.
enum EntryPoints {
HOME,
DASHBOARD,
SETTINGS,
}
enum Triggers {
RED_BUTTON,
BLUE_BUTTON,
YELLOW_BUTTON,
ORANGE_BUTTON,
}
In the HOME page we only have BLUE_BUTTON that trigger the modal.
In the DASHBOARD page we only have YELLOW_BUTTON and ORANGE_BUTTON.
In the SETTINGS page we only have BLUE_BUTTON and RED_BUTTON.
So far I defined a Discriminated Union to model this scenario, like so:
type HomeTriggers = {
entryPoint: EntryPoints.HOME
trigger: Triggers.BLUE_BUTTON
}
type DashboardTriggers = {
entryPoint: EntryPoints.DASHBOARD
trigger: Triggers.YELLOW_BUTTON | Triggers.ORANGE_BUTTON
}
type SettingsTriggers = {
entryPoint: EntryPoints.SETTINGS
trigger: Triggers.BLUE_BUTTON | Triggers.RED_BUTTON
}
type ModalTriggers = HomeTriggers | DashboardTriggers | SettingsTriggers
So when trying to use this in userland code:
function foo(trigger: ModalTriggers): void {}
foo({entryPoint: EntryPoints.HOME, trigger: Triggers.RED_BUTTON}) // --> throws error since RED_BUTTON is
// not present in the Home page
I was expecting a less criptic error or at least a good autocompletion from the IDE showing the possible values for trigger after providing an entryPoint (see image below)
