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
Literal type false unexpectedly widens into type boolean #25474
Expected behavior:
No error.. In the else clause, [foo2], it retains string | false so Array<string | false>. Logically since everything is taking place in the typings layer, foo2 should still be strongly bounded to false and will never be true.
Actual behavior:
Errors. In the else clause, [foo2], it expanded/loosened to string | boolean so Array<string | boolean>.
tmp.ts:7:1 - error TS2322: Type '(string | boolean)[]' is not assignable to type 'Foo'.
Type '(string | boolean)[]' is not assignable to type 'FooBase[]'.
Type 'string | boolean' is not assignable to type 'FooBase'.
Type 'true' is not assignable to type 'FooBase'.
7 foo1 = [...Array.isArray(foo2) ? foo2 : [foo2]];
~~~~
changed the title [-]Type of `false` unexpectedly loosens into type `boolean`[/-][+]Type of `false` unexpectedly widens into type `boolean`[/+]on Jul 5, 2018
The return type of trySomething is { result: boolean; message: string; } | { result: boolean; message?: undefined; } while it should be { result: false; message: string; } | { result: true; message?: undefined; }
If I use strictNullChecks and try to use a.message I will get an error saying it's possibly undefined.
Okay that probably makes some sense, typescript probably doesn't want to make the type too strict as users of the function may want to write values to the return value of the function.
This is an issue resulting from two separate factors:
We have non-widening forms of the string and numeric literal types (Non-widening explicit literal types #11126), but the true and false literal types and enum literal types are always considered widening.
Spread expressions aren't considered to have a contextual type.
Because the array literal [foo2] occurs in a spread expression it isn't contextually typed by FooBase (the type of foo1) and therefore the string | false type is widened to string | boolean. This very similar assignment has no issues because the contextual type propagates appropriately:
changed the title [-]Type of `false` unexpectedly widens into type `boolean`[/-][+]Literal type `false` unexpectedly widens into type `boolean`[/+]on Jul 6, 2018
Sorry, I feel like the answers I need are in this / #22596 but I can't grok it for the life of me
function x<Arg1, Arg2 extends (Arg1 extends true ? string[] : string)>(arg2IsArray: Arg1, arg2: Arg2){
}
x(true, 'string') // no error
x(true, ['string']) // no error
x(true as true, 'string') // error
x(true as true, ['string']) // no error
Is it that "true" means "boolean" if used in certain contexts to support
const x = true // x is a boolean not literally "true"?
But I just tried that and ts seems to think that x is just true not a boolean, idk. Anyway is there anyway to have the above example work without having to use true as true?
Activity
[-]Type of `false` unexpectedly loosens into type `boolean`[/-][+]Type of `false` unexpectedly widens into type `boolean`[/+]pedro-pedrosa commentedon Jul 6, 2018
Possibly related to this:
The return type of
trySomethingis{ result: boolean; message: string; } | { result: boolean; message?: undefined; }while it should be{ result: false; message: string; } | { result: true; message?: undefined; }If I use
strictNullChecksand try to usea.messageI will get an error saying it's possibly undefined.Playground link
Ghabriel commentedon Jul 6, 2018
Pedro Pedrosa (@pedro-pedrosa) I don't think it's related, TS always widens literals like that unless you do something like this, which works:
pedro-pedrosa commentedon Jul 6, 2018
Okay that probably makes some sense, typescript probably doesn't want to make the type too strict as users of the function may want to write values to the return value of the function.
cliffkoh commentedon Jul 6, 2018
Note that there isn't a bug with string literal types, only false/true into boolean
This works. type of
[foo2]in the conditional does not get widened intostring | string.ahejlsberg commentedon Jul 6, 2018
This is an issue resulting from two separate factors:
trueandfalseliteral types and enum literal types are always considered widening.Because the array literal
[foo2]occurs in a spread expression it isn't contextually typed byFooBase(the type offoo1) and therefore thestring | falsetype is widened tostring | boolean. This very similar assignment has no issues because the contextual type propagates appropriately:To fix this issue we need to propagate contextual types into spread expressions.
[-]Type of `false` unexpectedly widens into type `boolean`[/-][+]Literal type `false` unexpectedly widens into type `boolean`[/+]CS-Jfilmer commentedon Mar 5, 2020
Sorry, I feel like the answers I need are in this / #22596 but I can't grok it for the life of me
Is it that "true" means "boolean" if used in certain contexts to support
But I just tried that and ts seems to think that x is just true not a boolean, idk. Anyway is there anyway to have the above example work without having to use
true as true?