I have an union type in the core of my project.
type Shape = {kind: "circle", radius: number} | {kind: "square", size: number};
And I've decided to have a function to handle all the internals of updating a Shape
function update<T extends Shape>(obj: T, values: Partial<T>) {}
Because of my thorough typing, typescript does not allow me to do this:
const aShape = {} as Shape
aShape.size = 4 // this fails, because aShape could be a Circle
However with my update function it allows me to do all kind of weird things:
const aShape = {} as Shape
// this pass types checking even when Shape does not _always_ supports `size`
update(aShape, { size: 3 });
I kinda grasp the concept of excess property, and I kinda get why { size: 3 }
satisfies Partial<Shape>
. However I don't get why { unrelated: 3 }
won't.
But the weirdest thing I found, and I can't wrap my head around it, is that if I define my function using a non-op Omit modifier it behaves completely different:
type Shape = {kind: "circle", radius: number} | {kind: "square", size: number};
function update<T extends Shape>(obj: T, values: Omit<Partial<T>, "dont_care">) {}
const aShape = {} as Shape;
// this fails, as if you were trying to assign `size` to a `Shape`
update(aShape, { size: 3 });
This is the playground:
I am not sure what kind of answer I am expecting. Maybe if someone could explain why omitting a non-existing prop would radically change how typescript check my function calls it will make me more comfortable to production release such thing. Thanks for reading, cheers!