Closed
Description
TypeScript Version: 3.7.x-dev.201xxxxx
Search Terms: conditional type eager, conditional type narrowing
Code
type FooHelper<X> = (arg1: X, arg2: X extends 0 ? number : string) => void;
type Foo = FooHelper<0 | 1>;
let x: number;
const foo: Foo = (t, d) => {
if(t === 0) { x = d; }
}
Expected behavior:
No errors, t
has type 0 | 1
in the function body which gets narrowed to just 0
in the body of the if statement. In the if statement, d
should have type number, because we know that t
has to have type 0
.
Actual behavior:
Type 'string | number' is not assignable to type 'string'.
Related Issues: not really
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
jvanbruegge commentedon Oct 29, 2019
I also tried to define Foo differently:
But that infers
t
andd
both as anyRyanCavanaugh commentedon Oct 29, 2019
Foo
isn't a generic type, so the conditional has already been evaluated. Conditional types only stay unresolved when they're in a generic type.jvanbruegge commentedon Oct 29, 2019
So is it somehow possible to get the wanted behavior?
RyanCavanaugh commentedon Oct 29, 2019
Not really, no. You'd need #33014 at an absolute minimum - there's currently no mechanism that would allow for the kind of narrowing implied here.
jvanbruegge commentedon Oct 29, 2019
Sad. Ok, thank you
rubenpieters commentedon Nov 2, 2019
If I understand correctly, your intention is kind of like the following: the parameter
arg2
is dependent on the type ofarg1
. Actually, it is dependent on the value ofarg1
, but that is inexpressible.Unfortunately, just #33014 won't solve your problem (it is similar to the rejected case
a
here). Since the following can happen:Meaning: the value of
arg1
can be0
, while the type variableX
can be instantiated with0 | 1
, which means thatarg2
can actually hold astring
. As a result the logic of narrowingX
to0
based on the checkarg1 === 0
is unsound.We would additionally require something like #30284 to solve this.