-
Notifications
You must be signed in to change notification settings - Fork 12.8k
"Condition will always return false": declared type not being used? #42702
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
So let's say you wrote something like this declare function getCarOrPlaneOrBoat(): Car | Boat | Plane;
type CoolThing = Car | Boat | Plane | undefined;
const p: CoolThing = getCarOrPlaneOrBoat();
p.moveFast();
// ^ OK? Should this line error because The fact that that isn't an error is the exact reason that the OP is an error -- TS sees what you initialized the |
You can write |
Couldn't the same thing be said for the const p = "hello" as string | undefined;
console.log(p.length); Why is one case an "of course not"? And TS doesn't narrow in other cases: const x: string = "a";
if (x === "b") { // no error
console.log("b");
}
const y: unknown = 1;
if (y > 0) { // error
console.log('positive')
} Even though those seems similar to this: function g(x: string, y: unknown) {
if (x === "a") {
if (x === "b") { // error
console.log("b");
}
}
if (y === 1) {
if (y > 0) { // no error
console.log('2');
}
}
} I don't think narrowing "through" a declared type is fundamentally wrong. I'm just wondering if it's more useful to not do that. For one, the behavior was surprising to me and my coworkers. Maybe it's because the Also, I think it's common to use type declarations as a convenient "firewall" when messing around with code. For example, when debugging something, you might replace an expression with a constant, assuming that the type declaration keeps things modular. This is especially true when trying to figure out how to get code to type-check. I could retrain myself to use |
Non-union types such as |
Yeah, good point. I think the lack of narrowing contributed to the confusion I had, but it's sort of orthogonal to the core issue. The example in that issue also reminded me that I should distinguish between |
I think a good mental model for This isn't the case with a simple type annotation on a declaration - there TypeScript is free to use what it knows statically about your code in order to narrow the type. I feel pretty strongly (and I think the TS team do as well) that the default behaviour from an annotation is generally the most useful, and |
Initialization used to not act like narrowing and people complained because of the cases like the one I demonstrated. Moreover, it's very confusing if let x: T = e; behaves differently from let x: T;
x = e; Ultimately the code in the repro is indistinguishable from a logic error, there are many cases where you do want narrowing on initialization, and it's more consistent with assignment. It's a hard sell to make this less precise on purpose. We thought about this behavior before implementing it and are reasonably certain that this is the best available behavior. |
Suggestion
π Search Terms
union condition always return false inferred
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
Playground link
Since I've declared
x
to have type'a' | 'b'
, I was surprised that TypeScript didn't respect my declared type. But maybe TS does this a lot and I just haven't noticed?I think this is a useful error to report, but it feels like something you only want when you're ready to commit, like the "unused variable" warning. When I'm debugging/experimenting and moving a code around, I don't want this to prevent compilation.
π Motivating Example
See above.
π» Use Cases
See above.
The text was updated successfully, but these errors were encountered: