-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
No excess property checks when dealing with tagged unions #12745
Comments
We will need a proposal for this, since this has to take into consideration the discriminant property in the union and filter on this. |
Just ran into this. interface A {
type: "A";
data: { b: boolean };
}
interface B {
type: "B";
data: { n: number };
};
const x: A | B = {
type: "B",
data: { n: 1, excess: 2 }
}; |
Fix is up at #16363 |
Is the fact that the following is not checked for excess properties also related to this? In other words, should I open another issue on how the behavior is present regardless of the union being tagged? type Props<T> = PropsBase | PropsWithConvert;
interface PropsBase {
data: string;
}
interface PropsWithConvert extends PropsBase {
convert: (t: number) => string;
}
function doIt<T>(props: Props<T>) {
}
// 'convert' here returns a 'number', so it can't be assignable to 'PropsWithConvert',
// But the check still appears to succeed because the object is assignable to 'PropsBase'.
doIt({
data: "",
convert(x) {
return 10;
}
}) |
I'm not sure if this is completely fixed. I have code that looks like this: export type Condition = And | Or | Not | {
[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 = {
and: [],
not: { // <-- should be producing an error
equals: {
target: "name",
value: "foo"
},
},
} And there are no errors. Also if I do this there are no errors as well: const c: Condition = {
foo: "bar", // <--- should be error here. does not exist in any type
not: {
equals: {
target: "name",
value: "foo"
},
},
} |
@lukescott that's the intended behavior - a property isn't excess if it appears in any of the target types |
Ah - I missed |
@RyanCavanaugh ok I get how type Misc = {
[type: string]: {
target: string
[key: string]: any
}
} |
Your However, you should see a type error because |
oh, never mind. You're falling between two checks.
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. |
@lukescott I opened a bug #20060 to track your repro. I can't promise we'll do anything about it because we rely on the early-fail property of excess property checking for some speed in |
@sandersn Awesome, thank you! |
Version: 2.1.4
Expected: Excess property error on
value
in the object literal.Actual: No error.
The text was updated successfully, but these errors were encountered: