Conditional types are incorrectly narrowed
See original GitHub issueTypeScript Version: 3.1.6, 3.2.1, the current playground (3.3?), and next as of Feb 28
Search Terms: conditional types are incorrectly
Code
interface A { foo(); }
interface B { bar(); }
function test1<T extends A>(x: T, y: T extends B ? number : string) {
if (typeof y == 'string') {
y;
} else {
y; // never ?
}
const newY: string | number = y;
newY; // just string
}
function test2<T extends A>(x: T, y: T extends B ? string : number) {
if (typeof y == 'string') {
y; // never ?
} else {
y;
}
const newY: string | number = y;
newY; // just number
}
Expected behavior:
T extends B ? string : number
should either be left unchanged, or rounded up to string|number
: I think the issue stems from incorrect inference that T extends B
is false given T extends A
(while they’re just unrelated interfaces that have a non-empty intersection). The test case below is as far as I’ve managed to reduce the problem.
Actual behavior:
The T extends A
constraint seems to make TS guess T extends B
is always false, and so the a?b:c
type behaves as c
.
Playground Link: (playground)
Related Issues: https://github.com/Microsoft/TypeScript/issues/29939 looks slightly similar, but I don’t see the same constraints when playing around with my example, so I’m not sure it’s the same.
Issue Analytics
- State:
- Created 5 years ago
- Reactions:6
- Comments:17 (6 by maintainers)
Top GitHub Comments
We are having an issue at work that could be related:
It seems like when using generics the conditional type is not narrowed down as I would expect.
Should be mapped to
ImmutableMap<T>
always, independently of the type of T?Please correct me If I’m not understanding this correctly.
That commentary exists within the code that instantiates mapped types, that is, replaces type variables with types. Your example:
is a closed type and therefore is not subject to instantiation.
That is to say, when written:
there is more than just a basic inlining of
number
forT
going on.