Excess property check misses an error with union+string indexer
sandersn opened this issue · 3 comments
export type Condition = And | Or | Not | Misc
export interface Misc {
[type: string]: {
target: string
[key: string]: any
}
}
export interface And {
and: Condition[]
}
export interface Or {
or: Condition[]
}
export interface Not {
not: Condition
}
const c: Condition = {
foo: "bar", // <-- should be producing an error
not: {
equals: {
target: "name",
value: "foo"
},
},
}Expected behavior:
Error "foo is an excess property"
Actual behavior:
No error.
The excess property check is satisfied by Misc, which has a string indexer. No property will be marked as excess.
Structural assignability is satisfied by Not, since the object literal has the property not, but also an extra (excess!) property foo. But this is fine according to the rules of structural assignability.
The basic problem is that excess property checks happen before structural assignability finds the "best match" of the union; it uses a faster, heuristic check that doesn't perfectly match the exhaustive search used by structural assignability.
We could try moving excess property checking to the end of structuredTypeRelatedTo (or propertiesRelatedTo?) — object literals are guaranteed to reach this point, and they are the only things that are marked fresh right now. The code would be simpler because it wouldn't have to deal with unions. However, the performance gains from #16363 would very likely disappear.
It seems that it had been solved in version 3.8.
@axiac thanks!