The problem I've run into with the second approach as the number of states expand is 1 - you end up with tons of boilerplate to discriminate between types, and 2 - it becomes hard to treat objects polymorphically.
I sometimes end up doing {a: number, b?: undefined} | {b: string, a?: undefined} so that I can write `if (obj.a) doSomething()`, but it obviously gets unwieldy with a lot of properties and states. Imo it would be nice if TS did this automatically so that I could check for the existence of any property that might be defined on an object.