Radek Strnad
Radek Strnad

Reputation: 25

Use inferred type from union parameter in TypeScript function

Given type definition with fixed attribute names like

type Animals =
  | {
      key: 'dog';
      value: { woof: string };
    }
  | {
      key: 'cat';
      value: { meow: number };
    }

How do I construct a function parameters that will guarantee passing correct parameter at compile time to only a single type? I would like to call my function like:

fn('dog', { woof: 'woof' });
fn('cat', { meow: 'meow' });

but following should fail during compile time

fn('dog', { meow: 'meow' });
fn('cat', { woof: 'woof' });

I tried const fn = <T extends Animals>(key: T['key'], value: Extract<T, { key: T['key'] }>['value']) => ..., however value type remains of union type { woof: string } | { meow: number }, instead of exclusive { woof: string } or { meow: number } based on key parameter.

Upvotes: 0

Views: 43

Answers (1)

carlosV2
carlosV2

Reputation: 1399

Found a way to do it! To be fair I wasn't sure this was possible!

type Value<TKey, TAnimal extends Animals> = TAnimal extends { key: TKey, value: infer TValue } ? TValue : never;

function fn<TKey extends Animals['key'], TAnimal extends Animals>(key: TKey, value: Value<TKey, TAnimal>) {
   // Your code here
}

Take a look at this playgound.

Upvotes: 1

Related Questions