-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Types that depend on constants are not narrowing correctly #56417
Comments
Is this a real-world issue? I'd estimate that approximately nobody writes a ternary if they already know at compile time what the result is going to be. |
Sounds like a duplicate of #33912 to me. |
This is in fact a real-world issue (the example code is boiled down from our codebase). Our use case is that we are switching between two different versions of an API that return data via slightly different property paths. The objects returned by the API are used pretty deep in the codebase, and most of the property accesses will stay the same but a few will change. The BOOL in this case is used as a feature flag, and we'd like to switch between the true and false values rapidly during testing over the next few months. If we can get typechecks to pass with both values enabled, we'll be much more confident in the API transition. |
IMO that issue seems vastly more general than this one, and also it seems to be stuck in an unresolved (unresolvable?) debate about the correctness of that generalized implementation. However, I will defer to the Typescript maintainers, since y'all definitely know the codebase the best. |
Yeah this isnβt #33912 at all - thatβs about unresolved (i.e. generic) conditional types. The conditional type here is fully resolved, TS just doesnβt realize the ternary expression is always true. |
I should note that, today, if you write let foo;
if (true)
foo = 42;
else
foo = "fooey"; Then |
Note for implementers: as pointed out in #56417 (comment), if instead of a ternary you write this as an |
I'm not sure if this is going to be well-received if we "fix" it. The counterpart to this is people who have something like // Gets regex'd to 'false' in release builds
const DEBUG = true;
const foo: string = DEBUG ? something : something_else This introduces a danger if |
@RyanCavanaugh interesting point. Could we have the original proposed behavior only if I defer to your expertise, but my understanding is that defining a constant with Also, note: "ignoring" the un-taken branch is not a necessary condition for my original code example to work. We don't need to ignore the universe where |
π Search Terms
"ternary narrowing", "ternary constant", "constant narrowing", "constant dependent"
π Version & Regression Information
β― Playground Link
https://www.typescriptlang.org/play?ts=5.2.2#code/MYewdgzgLgBAQgeQQGRgXhlATgVwKYwCGEMokUAUBVAJ4AOBAKgPqO4EYDeMAHgFwxoWAJZgA5gBoYjAUNFiYAX2r0mzAGKEANhA4xu-QdnlT1s4+KVVaDaehgAKG3hAAzeEmQBKGHh5Q8MAATEmx8GAB+aVZ2GAEWTR08KgpXHDBgKGFwGFcHL3j9ChgS0nBoGAA3QiwZaLZwrl4BAHJq2papOpaxEBAglqtSsvIqmrNoxN17A1b29U6YCZaQAGtCGkHlYtKsPCgcLDAPFEix2rjz9QpFIA
π» Code
π Actual behavior
Typechecking fails with the error
Type 'T_True | T_False' is not assignable to type 'T_True'. Property 'T' is missing in type 'T_False' but required in type 'T_True'.
on the return statement.π Expected behavior
Typechecking should pass, since the
const BOOL = true as const
should mark thefalse
ternary case as unreachable.I also tried making T generic with respect to BOOL, and splitting the ternary operator into an if/else, but the same error persisted regardless.
Additional information about the issue
No response
The text was updated successfully, but these errors were encountered: