Open
Description
When comparing a generic type to a conditional type whose checkType is the same type, we have additional information that we are not utilizing.. for instance:
function f<T extends number>(x: T) {
var y: T extends number ? number : string;
// `T` is not assignable to `T extends number ? number : string`
y = x;
}
Ignoring intersections, we should be able to take the true branch all the time based on the constraint.
The intuition here is that T
in the example above is really T extends number ? T : never
which is assignable to T extends number ? number : string
.
Similarly, with substitution types, we have additional information that we can leverage, e.g.:
declare function isNumber(a: any): a is number;
function map<T extends number | string>(
o: T,
map: (value: T extends number ? number : string) => any
): any {
if (isNumber(o)) {
// `T & number` is not assignable to `T extends number ? number : string`
return map(o);
}
}