1

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!

rodix
  • 425
  • 4
  • 13

0 Answers0