Skip to content

No type narrowing for discriminated union type guards on unique symbol properties #23135

Closed
@kpdonn

Description

@kpdonn

Note: I know about #10530 but I explain why I think this deserves its own issue in the related issues section below

TypeScript Version: 2.9.0-dev.20180403

Search Terms:
unique symbol, discriminated union, type guard, narrow, narrowing

Code

declare const kind: unique symbol

type Square = {
  readonly [kind]: "square"
  length: number
  width: number
}

type Circle = {
  readonly [kind]: "circle"
  radius: number
}

type Shape = Square | Circle

function doesNotNarrow(shape: Shape) {
  if (shape[kind] === "square") {
    console.log(shape.length, shape.width) // error length does not exist on Shape 
  } else {
    console.log(shape.radius) // error radius does not exist on Shape 
  }
}

Expected behavior:
No errors because the type should be narrowed inside the if statements.

Actual behavior:
Compile errors because typescript does not narrow the type despite the discriminated union.

Playground Link:
Link

Related Issues:

I know this looks like a straight duplicate but I don't think it should be considered one because symbols aren't mentioned anywhere in that issue or in the titles of any of its duplicates, and unique symbol did not exist when that issue was originally considered.

The only reason that #10530 hasn't been fixed is because it caused enough of a performance slowdown that it wasn't considered a worthwhile tradeoff. I'm hoping that limiting this to only unique symbols will have a small enough performance impact to make it worthwhile this time.

Unlike most string keys, symbols can only be used with bracket notation so I think the value proposition here is much higher than it was for string keys. Plus it seems like using a symbol as a discriminant property that doesn't have to worry about conflicting with other property names is one of the most natural use cases for symbols.

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