Closed
Description
Bug Report
π Search Terms
"conditional type inference"
π Version & Regression Information
This changed between versions 4.1.5 and 4.2.2
β― Playground Link
Playground link with relevant code
π» Code
export interface IFruits {
tropical: {
papaya: number;
pineapple: number;
guava: number;
};
stone: {
peach: number;
nectarine: number;
};
berry: {
strawberry: number;
blueberry: number;
};
}
/**
* Aggregating all the second level keys (the fruits) into a single union type.
*/
export type FruitKey = {
[category in keyof IFruits]: keyof IFruits[category];
}[keyof IFruits];
/**
* Helper to pick only fruit categories (first level) that are required for the requested fruit keys.
*/
type RequiredFruitCategories<K extends FruitKey> = {
[category in keyof IFruits]: Extract<K, keyof IFruits[category]> extends never ? never : category;
}[keyof IFruits];
/**
* Takes a nested slice of the IFruits interface depending on the fruit keys (second level) that
* we ask for -- essentially a nested `Pick`. So `FruitsSubset<"papaya" | "peach">` ends up being:
* {
* tropical: {
* papaya: number;
* };
* stone: {
* peach: number;
* };
* }
*/
type FruitsSubset<K extends FruitKey> = {
[category in RequiredFruitCategories<K>]: Pick<
IFruits[category],
Extract<K, keyof IFruits[category]>
>;
};
/**
* Just wrapping the above in an interface for other interfaces (i.e. React props) to extend.
*/
interface FruitsSubsetOpts<K extends FruitKey> {
fruits: FruitsSubset<K>;
}
type MyFavoriteFruitsSubset = FruitsSubset<"papaya" | "peach">;
// Inferring the key from above -- this ends up being `"papaya" | "peach"` on TS 4.1.5 but `never` on 4.2.3
type MyFavoriteFruitsSubsetKey = MyFavoriteFruitsSubset extends FruitsSubset<infer K> ? K : never;
type MyFavoriteFruitsSubsetOpts = FruitsSubsetOpts<"papaya" | "peach">;
// Inferring the key from above -- this ends up being `"papaya" | "peach"` on both TS 4.1.5 and 4.2.3
// Pretty confusing because FruitsSubsetOpts is just a wrapper around FruitsSubset!
type MyFavoriteFruitsSubsetOptsKey = MyFavoriteFruitsSubsetOpts extends FruitsSubsetOpts<infer K> ? K : never;
π Actual behavior
MyFavoriteFruitsSubsetKey
can be properly inferred on TS 4.1.5 but not on 4.2.3 (we tried migrating to 4.2.2 locally and this broke so the change in behavior is somewhere between 4.1.5 and 4.2.2)
π Expected behavior
MyFavoriteFruitsSubsetKey
should be properly inferred on both versions. Could be we're doing a thing we shouldn't be doing in the first place, but it's strange that it only kind of breaks and doesn't completely break.