Idea is that there are two different interfaces called A and B, that has a validation and variant prop, and I am trying to write a function that takes only variant and validation values (field is already defined) to create an Example object.
I keep getting error at below highlighted code line, can someone kindly help to explain what’s going on here? Why ts complains? And any ts documentation that explain this behaviour?
export interface A {
field: "Af";
variant: "A";
validation: boolean;
}
export interface B {
field: "Af";
variant: "B";
validation: number;
}
export type C = A | B;
const c: C = {
field: "Af",
variant: "A",
validation: false,
};
class Example {
private data: C;
constructor(data: C) {
this.data = data;
}
}
const test = (type: Omit<C, "field">): Example => {
const d: C = { // should not throw error (Why throwing error here)
field: "Af",
...type,
};
const example = new Example(d);
return example;
};
test({ variant: "A", validation: true }); // should not throw error
test({ variant: "B", validation: 1 }); // should not throw error
test({ variant: "A", validation: 2 }); // should throw error
test({ variant: "B", validation: true }); // should throw error
Error I am getting is
Type '{ variant: "A" | "B"; validation: number | boolean; field: "Af"; }' is not assignable to type 'C'.
Type '{ variant: "A" | "B"; validation: number | boolean; field: "Af"; }' is not assignable to type 'B'.
Types of property 'variant' are incompatible.
Type '"A" | "B"' is not assignable to type '"B"'.
Type '"A"' is not assignable to type '"B"'.ts(2322)
>Solution :
The version of Omit in the base libraries is not distributive. So the resulting type will be an object type that mangles the union ({ variant: "A" | "B"; validation: number | boolean; field: "Af"; })
You ca easily write a distributive version of Omit though using distributive conditional types:
type DistributiveOmit<T, K extends PropertyKey> =
T extends T ? Omit<T, K> : never;
const test = (type: DistributiveOmit<C, "field">): Example => {
const d: C = { // ok
field: "Af",
...type,
};
//...
};