Closed
Description
Consider the following snippet,
/*
The below types are exactly the same.
The only difference is that one is wrapped in parentheses.
The other is not.
*/
type InvalidKeys<K extends string|number|symbol> = { [P in K]? : never };
type InvalidKeys2<K extends string|number|symbol> = (
{ [P in K]? : never }
);
type A<T> = (
T & InvalidKeys<"a">
);
type A2<T> = (
T & InvalidKeys2<"a">
);
/*
type a = {
x: number;
} & InvalidKeys<"a">
*/
type a = A<{ x : number }>;
/*
type a2 = {
x: number;
} & {
a?: undefined;
}
*/
type a2 = A2<{ x : number }>;
/*
One parentheses is all you need to change the output
*/
I've noticed that, sometimes, the presence/absence of parentheses can change the emitted type declaration. Is this intentional? If so, are there set rules for it? Can this behaviour be relied upon?
There are times where one would want the type to be expanded. And other times where one would not want the type to be expanded.
Having control over it would be nice. (I know I've wanted control over it plenty of times).
I have encountered this discrepancy multiple times but this is the most recent example,
(that inspired me to finally make this issue).
#20863 (comment)
The InvalidKeys
type is not expanded because I did not wrap the type in parentheses.
Obligatory @keithlayne , who hates unnecessary parentheses 🚎