-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Omit inferred type annotations for 'coalesce' arguments #5765
Conversation
9f80495
to
34c448d
Compare
34c448d
to
ed746cc
Compare
ed746cc
to
bf49b0f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than wrapping and unwrapping, did you consider an approach where parse
gets a flag from Coalesce.parse
indicating not to insert inferred assertions?
I considered that, but Realizing now that an alternative would be to just always wrap the coalesce in an outer assertion, even if none of its arguments are typed |
👍 always wrapping with an outer assertion. |
bf49b0f
to
867559c
Compare
867559c
to
9a8ca1c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, not really satisfied with how this turned out. The logic is complex and quite hard to follow.
Can we try another approach?
// Thus, if any of our arguments would have needed an annotation, we | ||
// need to wrap the enclosing coalesce expression with it instead. | ||
const needsAnnotation = expectedType && | ||
parsedArgs.some(arg => checkSubtype(expectedType, arg.type)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bit isn't strictly necessary -- we could just always return new Coalesce(ValueType, parsedArgs)
-- I figured including it would be more explicit & therefore clearer.
const expected = context.expectedType; | ||
const actual = parsed.type; | ||
if (expected) { | ||
// When we expect a number, string, or boolean but have a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about:
// When we expect a number, string, boolean, or array but
// have a Value, we can wrap it in a refining assertion.
// When we expect a Color but have a String or Value, we
// can wrap it in "to-color" coercion.
// Otherwise, we do static type-checking.
if ((expected.kind === 'string' || expected.kind === 'number' || expected.kind === 'boolean') && actual.kind === 'value') {
if (!options.omitTypeAnnotations) {
parsed = new Assertion(expected, [parsed]);
}
} else if (expected.kind === 'array' && actual.kind === 'value') {
if (!options.omitTypeAnnotations) {
parsed = new ArrayAssertion(expected, parsed);
}
} else if (expected.kind === 'color' && (actual.kind === 'value' || actual.kind === 'string')) {
if (!options.omitTypeAnnotations) {
parsed = new Coercion(expected, [parsed]);
}
} else if (context.checkSubtype(context.expectedType, parsed.type)) {
return null;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👌
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated with this approach.
6818962
to
d5709cd
Compare
As described in #5755, such inferred annotations cause a runtime type error for
null
inputs, thus preempting the desired null-coalescing behavior of something like["coalesce", ["get", "a"], ["get", "b"]]
.