You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Type 'true' is not assignable to type 'T2 extends keyof T1 ? true : false' #22735
In order for this to work you have to explicitly cast the return values to match the return type annotation because the type checker isn't capable of proving that it is always true:
But I'm wondering why you're using a conditional type in the return type annotation (as opposed to just boolean)?
This is just a simplified repro which happened to result in the same error. I actually want to type something slightly more complicated:
Case A: prop is a member of a specific union (here: keyof T1) => the function gets the design:type of target[prop] using Reflection and uses that for a lookup in a Record object.
Case B: prop is NOT a member of that union => the function returns null
I guess the error happens because (like you said) the type checker is not sure if the condition is fulfilled. However I'd expect that returning one of the possible outcomes of the conditional type should be possible.
What about this case? If I type it using string | null as a return value, y is incorrectly inferred as string.
functionensureString<T>(bar: T): Textendsstring ? string : null{if(typeofbar==="string")returnbarasstring;// ^ ERROR: string is not assignable to T extends string ? string : nullreturn;}varx=ensureString("");// correctly inferred as stringvary=ensureString(1);// correctly inferred as null
but is the behavior I described in my last post intended?
it is expected given the current design. but it is more of a design limitation than a desired behavior.
The type of bar is narrowed in the if statement to T & string, neither that nor string are assignable to T extends string ? string : null, since the return type really depends on T, and string does not have that par in it.
in a sense what you need the compiler to do here is 1. narrow the type of bar to T extends string, and thus the type of the return statement to T extends string ? string : never, then narrow the type of bar on the else branch to T extends string ? never : null, then unify the two return statements into one return type which is T extends string? string : null which is the same as the declared type. but the compiler is not geared to do this at the moment.
you can cast your way out of this using a conditional type using T , e.g.:
if(typeofbar==="string")return<Textendsstring ? T : never>bar;
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.
Activity
RyanCavanaugh commentedon Mar 20, 2018
Likely duplicate of #22596
ahejlsberg commentedon Mar 21, 2018
In order for this to work you have to explicitly cast the return values to match the return type annotation because the type checker isn't capable of proving that it is always true:
But I'm wondering why you're using a conditional type in the return type annotation (as opposed to just
boolean)?Ryan Cavanaugh (@RyanCavanaugh) This is unrelated to #22596.
AlCalzone commentedon Mar 21, 2018
This is just a simplified repro which happened to result in the same error. I actually want to type something slightly more complicated:
propis a member of a specific union (here:keyof T1) => the function gets thedesign:typeoftarget[prop]usingReflectionand uses that for a lookup in aRecordobject.propis NOT a member of that union => the function returns nullI guess the error happens because (like you said) the type checker is not sure if the condition is fulfilled. However I'd expect that returning one of the possible outcomes of the conditional type should be possible.
What about this case? If I type it using
string | nullas a return value, y is incorrectly inferred asstring.AlCalzone commentedon Mar 28, 2018
Sorry for bringing this up again... but is the behavior I described in my last post intended?
mhegazy commentedon Mar 28, 2018
it is expected given the current design. but it is more of a design limitation than a desired behavior.
The type of
baris narrowed in the if statement toT & string, neither that norstringare assignable toT extends string ? string : null, since the return type really depends onT, andstringdoes not have that par in it.in a sense what you need the compiler to do here is 1. narrow the type of
bartoT extends string, and thus the type of the return statement toT extends string ? string : never, then narrow the type of bar on the else branch toT extends string ? never : null, then unify the two return statements into one return type which isT extends string? string : nullwhich is the same as the declared type. but the compiler is not geared to do this at the moment.you can cast your way out of this using a conditional type using
T, e.g.:AlCalzone commentedon Mar 29, 2018
Alright, thanks for the explanation!
typescript-bot commentedon Apr 12, 2018
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.