-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Type 'true' constants behave differently than 'true' literal #29323
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
Comments
I actually abuse this bug to have type-only assertions written as unreachable runtime code 😅 If I write code intended to assert types inside an I say this is related because the |
// subscribe cc @DanielRosenwasser also :-) |
Background: The control flow graph creator can't resolve the types of expressions (doing so would create a circular dependency between passes of the compiler), but does have some logic for detecting What's the reason for writing code like this? It seems like you'd only want to do this if you wanted |
The goal is to be able to remove those checks using a minification pass at your own risk. I understand that the output code would break the type contract. The above snippet could be written as follow: function ensureValue<T>(value: T | null): T {
if (__TRUE__) {
if (value === null) {
throw new Error();
}
}
return value!;
// ^
} But I tried to see if it was possible to achieve the same result without using TypeScript syntax extension. Moreover, since |
It does seem odd that function f(x: boolean) {
if (!x) { return; }
// here `x` is known to be `true`
} |
@ljharb type MapBool<T> = T extends true ? "true" : T extends false ? "false" : never;
type B = MapBool<boolean>; // "true" | "false"; Your example narrows correctly for me. function f(x: boolean) {
if (!x) {
const f: false = x;
return;
}
const t: true = x;
} You need |
In that case, why wouldn’t the OP’s type of |
The control flow graph handles type narrowing, and is used to essentially answer the question: "Is the test As @RyanCavanaugh already described, there are no types involved when building the graph. The reason the From the point of view of the graph, and trying to answer the "Always/Sometimes/Never" reachability question, the identifier
The graph doesn't know the identifier will always evaluate to (Please correct me if I'm wrong!) |
TypeScript Version: 3.3.0-dev.20190108
Search Terms:
Code
Expected behavior:
ensureValue
has a correct return type whenstrictNullChecks
is enabled.In other words, if a constant is typed as
true
, I expect it to behave liketrue
literal.In the above example, both
if
statements should infer the types the same way.Actual behavior:
There is a type error when
strictNullChecks
is enabled:Please note that
if (true)
works as expected.Playground Link:
http://www.typescriptlang.org/play/#src=function%20ensureValue%3CT%3E(value%3A%20T%20%7C%20null)%3A%20T%20%7B%0D%0A%20%20if%20(true)%20%7B%0D%0A%20%20%20%20if%20(value%20%3D%3D%3D%20null)%20%7B%0D%0A%20%20%20%20%20%20throw%20new%20Error()%0D%0A%20%20%20%20%7D%0D%0A%20%20%7D%0D%0A%20%20return%20value%20%2F%2F%20OK%0D%0A%7D%0D%0A%0D%0Adeclare%20const%20__TRUE__%3A%20true%0D%0A%2F%2F%20Same%20error%20using%20variable%20declaration%3A%0D%0A%2F%2F%20const%20__TRUE__%3A%20true%20%3D%20true%0D%0Afunction%20ensureValueWithConstant%3CT%3E(value%3A%20T%20%7C%20null)%3A%20T%20%7B%0D%0A%20%20if%20(__TRUE__)%20%7B%0D%0A%20%20%20%20if%20(value%20%3D%3D%3D%20null)%20%7B%0D%0A%20%20%20%20%20%20throw%20new%20Error()%0D%0A%20%20%20%20%7D%0D%0A%20%20%7D%0D%0A%20%20return%20value%20%2F%2F%20Hmm%0D%0A%7D
Related Issues:
The text was updated successfully, but these errors were encountered: