Closed
Description
Suppose I have a union of two types which are completely distinguishable based on their keys:
type Foo = { x: number } | { y: string }
I'd like to do case analysis on this union in a typesafe way. I would think using in
would work, but it doesn't:
function f(foo: Foo) {
if ('x' in foo) {
// Type error: Property 'x' does not exist on type '{ y: string; }'
console.log(foo.x + 5)
} else {
// Type error: Property 'y' does not exist on type '{ x: number; }'
console.log(foo.y.length)
}
}
However I'm able to define a type guard which does the trick:
export function hasKey<K extends string>(k: K, o: {}): o is { [_ in K]: {} } {
return typeof o === 'object' && k in o
}
// Now this works:
function f(foo: Foo) {
if (hasKey('x', foo)) {
console.log(foo.x + 5)
} else {
console.log(foo.y.length)
}
}
Is there a more correct built-in way to do this that I'm missing? It seems like this is something in
should provide out of the bag.