typescripttypesalgebraic-data-types

Extract<T, U> in typescript behaves differently than discriminating T "by hand"


Given a simple union, I'm trying to extract one type. I ran into this dealing with more complex objects, but it's reproduced with string literals here:

type PQR = 'p'|'q'|'r';
type P = 'p'
// this results in 'p'
type JustP = Extract<PQR, P>;
// this results in never
type NeverP = PQR extends P ? PQR : never;

example in typescript playground

I would have assumed that both of the following would have done that, but only the first one does. The second one appears to not distribute the conditional over members of PQR, as far as I can tell. If you hover over Expect in the typescript playground, it suggests exactly the right-hand side NeverP from my example. Is there something special about generic parameters causing this to happen?


Solution

  • https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types

    Seems I missed this in the documentation:

    When conditional types act on a generic type, they become distributive when given a union type.

    seems obvious now, though.