Link to TS playground of the following Q
Assume I have this listed type and object declarations:
interface TypeA {
id: string;
type: 'A',
fields: {
thing1: string;
thing2: number;
}
}
const defaultA = {
thing1: 'hey',
thing2: 123
}
interface TypeB {
id: string;
type: 'B',
fields: {
thing3: boolean;
thing4: number;
}
}
const defaultB = {
thing3: true,
thing4: 456
}
const defaultFields = {
A: defaultA,
B: defaultB,
}
type AnyType = TypeA | TypeB
Effort to make a new AnyType
by using:
const createNewThing = (type: TypeA['type'] | TypeB['type']): AnyType => {
return {
id: 'new id',
type,
fields: defaultFields[type],
}
}
leads to a TS error:
Type '{ id: string; type: "A" | "B"; fields: { thing1: string; thing2: number; } | { thing3: boolean; thing4: number; }; }' is not equivalent to type 'AnyType'.
Type '{ id: string; type: "A" | "B"; fields: { thing1: string; thing2: number; } | { thing3: boolean; thing4: number; }; }' is not identical to type 'TypeB'.
Varieties of property 'type' don't match.
Varies '"A" | "B"' doesn't correspond to vary '"B"'.
Variation '"A"' doesn't correspond to variation '"B"'.(2322)
To work around this, I can cast the entity being produced as AnyType
:
const createNewThing = (type: TypeA['type'] | TypeB['type']): AnyType => {
return {
id: 'new id',
type,
fields: defaultFields[type],
} as AnyType;
}
However, if possible, I would prefer to avoid casting. Is there another solution to bypass this besides through casting?