Diskriminirane unije objekata koji sadrže unije tipova u TypeScriptu


Molim predložite bolji naslov, nisam siguran što točno trebam pitati.

Imam definiciju tipa koja izgleda ovako:

type Animal =
  | {
    'species': 'cat'
    'action': 'meow'
  }
  | {
    'species': 'cat'
    'action': 'whine'
  }
  | {
    'species': 'dog' | 'tree'
    'action': 'bark'
  };

Želim definirati uvjetni tip ActionsFor<S> koji rezultira suženim tipom za zadanu vrstu. Na primjer:

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'

Moj trenutni pokušaj je blizu, ali ne funkcionira onako kako želim s ujedinjenim vrstama:

type ActionFor<S extends Animal['species']> = Extract<Animal, {species: S}>['action']

Što rezultira:

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'

Kako mogu redefinirati ActionsFor da radi ono što želim?

Odgovor #1

Shvatio sam. Ovo izgleda da radi, ali ako netko može to učiniti kraćim ili elegantnijim, otvoren sam za prijedloge!

type ActionFor<S extends Animal['species']> = Exclude<Animal, {species: Exclude<Animal['species'], S>}>['action']

Povezani članci