The compiler will not let you access properties on a union type unless every member of the union has a known property at that key:
type U = { id: string, weight: string } | { id: string }
declare const u: U;
u.id.toUpperCase(); // okay
u.weight // error! Property 'weight' does not exist on type '{ id: string; }'.
This is because object types in TypeScript are not sealed or exact. It is technically possible for a value of type {id: string} to contain extra properties like weight (although excess property checking can complicate this):
const something = { id: "abc", weight: 123 }
const oops: U = something; // this is accepted
That compiles because someThing matches {id: "abc"}, and weight of type number doesn't invalidate that. You were assuming that a value of type U either had a string-valued weight property, or was missing the weight properly entirely. But the assignment const oops: U = something shows that this assumption is technically incorrect, and that's the problem you're running into.
There are a few ways around this. You could explicitly prohibit weight on the second union element, by making it an optional property whose value is the impossible never type:
type U = { id: string, weight: string } | { id: string, weight?: never }
// now weight is known in every member of the union --> ^^^^^^^^^^^^^^
declare const u: U;
u.weight // okay, string | undefined
const something = { id: "abc", weight: 123 }
const oops: U = something; // error!
That works now; the type of u.weight is known to be either string or undefined. And the compiler catches the assignment of something to oops because now {id: string, weight: number} is no longer assignable to U. That is, now it is correct to assume that weight is either present and string-valued, or absent (more or less).
A less intrusive fix is to use a narrowing technique that makes the same technically-incorrect assumption as you were making. The compiler will treat use of the in operator as a way to narrow a union-typed value to those union members known to have the checked property:
"weight" in u ? u.weight : undefined // okay, string | undefined
When the "weight" in u check is true, the compiler assumes that u.weight is of type string, so it lets you evaluate u.weight. This narrowing is technically unsafe, so this method is only appropriate if you can be relatively sure that the oops assignment will happen. After all, that still compiles without error:
const something = { id: "abc", weight: 123 }
const oops: U = something; // still no error
But as long as your code doesn't do things like that, in-operator narrowing should work for you.
Playground link to code
el, andComponent.cosntin there, for example). Reduce instead of expanding where possible. Like theOrigsection here.