Skip to content

Destructuring breaks tagged union case inference #23613

Closed

Description

@bcherny

TypeScript Version: 2.8.3

Search Terms: union, destructure

Code

type Message =
    { type: 'sendMessageToThread', data: { threadId: number, message: string }}
  | { type: 'createThread', data: { userIds: number[] }}
  | { type: 'addUserToThread', data: { threadId: number, userId: number }}

// Good case
function a(message: Message) {
  switch (message.type) {
    case 'sendMessageToThread':
      console.log(message.data.threadId)
  }
}

// Bad case
function b({ type, data }: Message) {
  switch (type) {
    case 'sendMessageToThread':
      // Error: Property 'threadId' does not exist on type
      console.log(data.threadId)
  }
}

Expected behavior:

TS should infer which case the tagged union falls into regardless of whether or not the parameter is destructured. data should be inferred as { threadId: number, message: string }.

Actual behavior:

data is inferred as the union of all data values in Message.

Playground Link

Activity

  1. mhegazy commented on Apr 23, 2018

    @mhegazy
    Contributor

    Duplicate of #14630, and #15482

  2. bcherny commented on Apr 23, 2018

    @bcherny
    Author

    Thanks for digging up those issues Mohamed Hegazy (@mhegazy). This seems like a real issue, so I'm not sure why those were closed out. Maybe it's worth keeping one of them open to track the issue? This is pretty surprising behavior from a user's point of view.

  3. mhegazy commented on Apr 23, 2018

    @mhegazy
    Contributor

    I would merge this in #9998. these are design limitation for how control flow analysis is implemented.

  4. bcherny commented on Apr 28, 2018

    @bcherny
    Author

    Sounds good to me.

  5. locked and limited conversation to collaborators on Jul 31, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions