You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I started playing around with excess property checking for unions without discriminant properties, proof-of-concept. (Currently it's a hack). Before ploughing on with any more work I thought it was best to get some feedback.
When computing known properties retain a set of type id's for pruned types that have failed previous excess property checks. When checking later properties we cannot use these pruned types as evidence that the property is not 'excess'.
On checking property x we prune type {y: string} because x is excess. When checking y, we cannot use type {y: string} as it was previously pruned, therefore we only have {x: number} which is also excess. The snippet of the code that checks this can be found at the bottom (knowPropertyWithPruning).
Real Examples:
The proof-of-concept catches the error for the example in #20863, marking author as excess.
Using pruned set post excess property checks.
The pruned set can be used even when an excess property violation was not found. After the check, filter the target type by the pruned types to prevent assignment to branches in a union that have been violated by excess property checking. The p-o-c catches errors for the following examples:
In this example we get an error because PropBase gets pruned in excess property checking so the function convert must satisfy the type in PropsWithConvert.
In this example we get an error on passes because excess property checking prunes B, so z must satisfy boolean.
The example in #20060 is also flagged as an error.
Limitations
It does not catch the error here. The problem is that excess property checking is only 1-deep at a time. After the first level (which has no excess properties), the type is no longer marked as a fresh literal so the deeper checks don't look for excess properties (using getRegularTypeOfObjectLiteral). I tried changing this to only mark 1 level at a time, but it caused a perf regression.
I've not looked into perf impact with this. The main extra work that is being done is not short-circuiting the known property traversal for union types, as we want to prune all types. If there is a fast discriminant check then we can only add this extra cost when needed. I would be interested to know if there was a perf improvement in the isRelatedTo check for a union that has had some branches pruned by excess property checks.
Error Messages
I didn't do anything with the error messages and consequently they can be pretty awful. The problem is that it can be multiple properties that contribute to the error, but only the last gets flagged. E.g.:
typeFoo={x: number}|{y: string};lettest: Foo={x: 4,y: "hello"};// error.// Type '{ x: number; y: string; }' is not assignable to type 'Foo'.// Object literal may only specify known properties,// and 'y' does not exist in type 'Foo'. [2322]
The property y gets flagged here because it's the last, but x could be equally responsible. Furthermore, the claim that y is not in Foo is completely misleading. I think good error reporting is really important here: I'm open to any suggestions.
The text was updated successfully, but these errors were encountered:
jack-williams
changed the title
Proposal / Suggestion : Excesses Property Checking Without Discriminant Properties.
Proposal / Suggestion : Excesses Property Checking for Union Without Discriminant Properties.
Apr 19, 2018
jack-williams
changed the title
Proposal / Suggestion : Excesses Property Checking for Union Without Discriminant Properties.
Proposal / Suggestion : Excess Property Checking for Union Without Discriminant Properties.
Apr 19, 2018
I started playing around with excess property checking for unions without discriminant properties, proof-of-concept. (Currently it's a hack). Before ploughing on with any more work I thought it was best to get some feedback.
Related: #20863 #12745 #20060
Idea:
When computing known properties retain a set of type id's for pruned types that have failed previous excess property checks. When checking later properties we cannot use these pruned types as evidence that the property is not 'excess'.
Basic Example:
On checking property
x
we prune type{y: string}
becausex
is excess. When checkingy
, we cannot use type{y: string}
as it was previously pruned, therefore we only have{x: number}
which is also excess. The snippet of the code that checks this can be found at the bottom (knowPropertyWithPruning
).Real Examples:
The proof-of-concept catches the error for the example in #20863, marking
author
as excess.Using pruned set post excess property checks.
The pruned set can be used even when an excess property violation was not found. After the check, filter the target type by the pruned types to prevent assignment to branches in a union that have been violated by excess property checking. The p-o-c catches errors for the following examples:
In this example we get an error because
PropBase
gets pruned in excess property checking so the functionconvert
must satisfy the type inPropsWithConvert
.In this example we get an error on
passes
because excess property checking prunesB
, soz
must satisfyboolean
.The example in #20060 is also flagged as an error.
Limitations
It does not catch the error here. The problem is that excess property checking is only 1-deep at a time. After the first level (which has no excess properties), the type is no longer marked as a fresh literal so the deeper checks don't look for excess properties (using
getRegularTypeOfObjectLiteral
). I tried changing this to only mark 1 level at a time, but it caused a perf regression.I've not looked into perf impact with this. The main extra work that is being done is not short-circuiting the known property traversal for union types, as we want to prune all types. If there is a fast discriminant check then we can only add this extra cost when needed. I would be interested to know if there was a perf improvement in the
isRelatedTo
check for a union that has had some branches pruned by excess property checks.Error Messages
I didn't do anything with the error messages and consequently they can be pretty awful. The problem is that it can be multiple properties that contribute to the error, but only the last gets flagged. E.g.:
The property
y
gets flagged here because it's the last, butx
could be equally responsible. Furthermore, the claim thaty
is not inFoo
is completely misleading. I think good error reporting is really important here: I'm open to any suggestions.Appendix
The text was updated successfully, but these errors were encountered: