This is kind of a strange edge case that it took me several hours to figure out, but I don’t know what typescript rule is causing it, so I’m curious if this is something I’m not aware of, or if it’s a bug in my typescript interpreter.
I have a type where I want an extra field (allowedValues
) only if a different field has a particular value (selection
). I wrote a union type that looks like this:
type AttributeTypeOptional = {
type: 'textField';
} | {
type: 'selection';
allowedValues: {[key: string]: string};
};
Since I had a lot of mock data, I didn’t want to write the type over and over, so I made a default object and then spread it into each result. (There would also be other fields here, but they aren’t relevant to the problem.)
const defaults = {
type: 'textField';
};
When I did this, objects with the default value for type: textField
would expect allowedValues
. BUT, if I included the type directly in the object, the error would go away.
results: [
{
...defaults, // <-- expects allowedValues (incorrectly).
},
{
...defaults,
type: 'textField', // <-- does not expect allowedValues (correct)
},
{
...defaults,
type: 'selection', // <-- expects allowedValues (correct)
allowedValues: {"1": "1", "2": "2"}
},
]
It seems like including a value from a spread shouldn’t have an effect on whether the type gets correctly asserted. I’ve also tried this with enums instead of strings and had the same problem. (I actually rewrote this when I deduced that the enum wasn’t part of the problem as I originally thought.)
The specific error I’m getting is:
Type ‘{ name: string; description: string; type: string; }’ is not assignable to type ‘AttributeType’.
Type ‘{ name: string; description: string; type: string; }’ is not assignable to type ‘{ type: “selection”; allowedValues: { [key: string]: string; }; } & { name: string; description: string | null; }’.
Property ‘allowedValues’ is missing in type ‘{ name: string; description: string; type: string; }’ but required in type ‘{ type: “selection”; allowedValues: { [key: string]: string; }; }’.
Here’s a link to a slightly more complete version with the error in TS 5.7.3: