Looking for advice on how to create a specific type definition based on species.
Take a look at my current type definition:
type Animal =
| {
'species': 'cat'
'action': 'meow'
}
| {
'species': 'cat'
'action': 'whine'
}
| {
'species': 'dog' | 'tree'
'action': 'bark'
};
I need help defining a conditional type ActionsFor<S>
that will narrow down the type based on the given species. For example:
type CatActions = ActionsFor<'cat'> // should be 'meow' | 'whine'
type DogActions = ActionsFor<'dog'> // should be 'bark'
type TreeActions = ActionsFor<'tree'> // should be 'bark'
type BarkActions = ActionsFor<'dog'|'tree'> // should be 'bark'
My current implementation is almost there, but does not handle unioned species correctly:
type ActionFor<S extends Animal['species']> = Extract<Animal, {species: S}>['action']
This leads to:
type CatActions = ActionsFor<'cat'> // correct - 'meow' | 'whine'
type DogActions = ActionsFor<'dog'> // WRONG - never
type TreeActions = ActionsFor<'tree'> // WRONG - never
type BarkActions = ActionsFor<'dog'|'tree'> // correct - 'bark'
Any suggestions on how to redefine ActionsFor to achieve the desired outcome?