Description
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:
- Discriminant property type guard not applied with bracket notation #10530 Discriminant property type guard not applied with bracket notation
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 symbol
s 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.