TypeScript generics work when you call it but not in the function body?
14:58 09 Sep 2022

Say I have this example:

type Keys = 'one' | 'two';
type Values = T extends 'one' 
  ? { id: 1, name: 'hello1' } 
  : T extends 'two' 
    ? { id: 2, value: 'hello2' }
      : never;

type Fn = (key: T) => (value: Values) => void;

const fn: Fn = (key) => (value) => {
  if (key === 'one') {
    const name = value.name; // This throws compile error
  }
}

// Both of these `fn` calls correctly limit the `value` argument based on the `key`
fn('one')({ id: 1, name: 'hello1' });
fn('two')({ id: 2, value: 'hello2' });

Can someone explain to me why this setup correctly limits the allowed types for the value argument when invoking the fn method, but doesn't allow me to narrow value after using a Type Guard inside the fn implementation?

Playground - I have this playground with a few other attempts to make this work, but not success.

Ultimately I'm trying to use something similar to this as a useCallback method in a React project where an onChange prop is set with the callback invoked with a key, then the event sends the value. Since I know the types of the event, I feel like this should be possible. Ex:



typescript