Skip to content
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

Object type is not narrowed correctly after type guards have been applied to its fields #24639

Closed
ronp001 opened this issue Jun 3, 2018 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@ronp001
Copy link

ronp001 commented Jun 3, 2018

TypeScript Version: 3.0.0-dev.201xxxxx
Reproduced in 3.0.0-dev.20180602

Search Terms:
is:issue is:open type narrowing interface
is:issue is:open type narrowing object
is:issue is:open TS2322

Code

type ObjectWithRequiredId = { id: number }
type ObjectWithOptionalId = { id?: number }

const obj_with_optional_id: ObjectWithOptionalId = { id: 1 }

if (typeof obj_with_optional_id.id === "number") {
  const id: number = obj_with_optional_id.id // correctly, no error emitted here - type guard recognizes that record_with_optional_id.id is not 'undefined'
  let record: ObjectWithRequiredId = obj_with_optional_id // unexpected error received here
}

Expected behavior:

The assignment let record: ObjectWithRequiredId = obj_with_optional_id should be allowed.

In other words, the variable of type ObjectWithOptionalId should be narrowed to become equivalent to ObjectWithRequiredId after the optional id field has passed the typeof type guard.

Actual behavior:

error TS2322: Type 'ObjectWithOptionalId' is not assignable to type 'ObjectWithRequiredId'.
  Types of property 'id' are incompatible.
    Type 'number | undefined' is not assignable to type 'number'.
      Type 'undefined' is not assignable to type 'number'.

8   let record: ObjectWithRequiredId = obj_with_optional_id // unexpected error received here

Playground Link:

http://www.typescriptlang.org/play/#src=type%20ObjectWithRequiredId%20%3D%20%7B%20id%3A%20number%20%7D%0D%0Atype%20ObjectWithOptionalId%20%3D%20%7B%20id%3F%3A%20number%20%7D%0D%0A%0D%0Aconst%20obj_with_optional_id%3A%20ObjectWithOptionalId%20%3D%20%7B%20id%3A%201%20%7D%0D%0A%0D%0Aif%20(typeof%20obj_with_optional_id.id%20%3D%3D%3D%20%22number%22)%20%7B%0D%0A%20%20const%20id%3A%20number%20%3D%20obj_with_optional_id.id%20%2F%2F%20correctly%2C%20no%20error%20emitted%20here%20-%20type%20guard%20recognizes%20that%20record_with_optional_id.id%20is%20not%20'undefined'%0D%0A%20%20let%20record%3A%20ObjectWithRequiredId%20%3D%20obj_with_optional_id%20%2F%2F%20unexpected%20error%20received%20here%0D%0A%7D%0D%0A

Related Issues:

@mhegazy
Copy link
Contributor

mhegazy commented Jun 4, 2018

Duplicate of #20127 and #18758

@mhegazy mhegazy added the Duplicate An existing issue was already created label Jun 4, 2018
@ronp001
Copy link
Author

ronp001 commented Jun 4, 2018

Thanks @mhegazy. Looking at the other issues you mentioned I see that this might be a bit difficult to fix.

In the mean time, perhaps consider improving the error message? The current error is misleading (the message is "Type 'number | undefined' is not assignable to type 'number", where clearly the field type is 'number' and not 'number | undefined')

This error got me wasting quite a bit of time trying to figure out what was wrong with my complex react-native/babel/vscode/jest/typescript configuration. It took me a while to identify that this was a core typescript issue and not a configuration problem.

@mhegazy
Copy link
Contributor

mhegazy commented Jun 4, 2018

In the mean time, perhaps consider improving the error message?

the error message falls off from not narrowing the type. when the error message is reported it is too late to know what error message to report. #18758 tracks addressing the underlying issue.

@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants