Reputation: 25
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
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