Skip to content

Annotation of boolean type ignore in favor of narrowed type #31734

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

Closed
drew-gross opened this issue Jun 3, 2019 · 6 comments
Closed

Annotation of boolean type ignore in favor of narrowed type #31734

drew-gross opened this issue Jun 3, 2019 · 6 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@drew-gross
Copy link

TypeScript Version: 3.5.1

Search Terms:

Boolean explicit annotation ignore

Code

// Errors as expected
let bothInferred = true;
if (bothInferred == false) { }

// Doesn't error as expected 
let bothExplicit: boolean = true as boolean;
if (bothExplicit == false) { }

// Doesn't error as expected
let leftInferredRightExplicit = true as boolean;
if (leftInferredRightExplicit == false) { }

// Why error? Narrow rhs overrides explicit declaration.
let rigthInferredLeftExplicit: boolean = true;
if (rigthInferredLeftExplicit == false) { }

Expected behavior:

4th example above shouldn't error.

Actual behavior:

Error: This condition will always return 'false' since the types 'true' and 'false' have no overlap.

Playground Link:

https://www.typescriptlang.org/play/#src=%2F%2F%20Errors%20as%20expected%0D%0Alet%20bothInferred%20%3D%20true%3B%0D%0Aif%20(bothInferred%20%3D%3D%20false)%20%7B%20%7D%0D%0A%0D%0A%2F%2F%20Doesn't%20error%20as%20expected%20%0D%0Alet%20bothExplicit%3A%20boolean%20%3D%20true%20as%20boolean%3B%0D%0Aif%20(bothExplicit%20%3D%3D%20false)%20%7B%20%7D%0D%0A%0D%0A%2F%2F%20Doesn't%20error%20as%20expected%0D%0Alet%20leftInferredRightExplicit%20%3D%20true%20as%20boolean%3B%0D%0Aif%20(leftInferredRightExplicit%20%3D%3D%20false)%20%7B%20%7D%0D%0A%0D%0A%2F%2F%20Why%20error%3F%0D%0Alet%20rigthInferredLeftExplicit%3A%20boolean%20%3D%20true%3B%0D%0Aif%20(rigthInferredLeftExplicit%20%3D%3D%20false)%20%7B%20%7D%0D%0A

Related Issues:

Tried similar patterns with other types, could not find an error.

@ajafff
Copy link
Contributor

ajafff commented Jun 3, 2019

Union types are narrowed on assignment. boolean is a union type true | false behind the scenes

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Jun 3, 2019
@drew-gross
Copy link
Author

Ah yeah I could reproduce the error with a different union type

type U = "a" | "b";

let u: U = "a";

if (u == "b") {
    console.log();
}

Seems like an explicit annotation should override narrowing though? Explicit seems like it should always win over any type of inference.

@RyanCavanaugh
Copy link
Member

Seems like an explicit annotation should override narrowing though?

Intuitively, there should really not be a difference between

let u: U = "a";
/* some statement */

and

let u: U;
u = "a";
/* some statement */

@drew-gross
Copy link
Author

Huh, intuitively I think of the things on the left of an assignment as happening after the things on the right. Maybe this is my C++ background coming through (https://godbolt.org/z/VvVzbE). I guess for javascript both ways are equally valid though.

@jcalz
Copy link
Contributor

jcalz commented Jun 27, 2019

Cross-linking to #8513, of which this issue is arguably a duplicate

@matt-tingen
Copy link

This behavior is unintuitive to me, as well. In particular, with aliased object types, adding a widening type annotation can actually result in narrowing:

type Open = { isOpen: true };
type Closed = { isOpen: false };
type Status = Open | Closed;

const openBare = { isOpen: true };
const openAnnotated: Status = { isOpen: true };

type Bare = typeof openBare; // { isOpen: boolean }
type Annotated = typeof openAnnotated; // { isOpen: true }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

6 participants