Repository navigation
Description
🐞 bug report
Affected Package
The issue is caused by package @angular/coreIs this a regression?
Yes, the previous version in which this bug was not present was: 1.xDescription
AngularJS: a ? b : c | x means (a ? b : c) | x.
Angular: a ? b : c | x means a ? b : (c | x).
It is unexpected. E.g. see #19657, prettier/prettier#5586.
Who would write a ? b : c | x meaning a ? b : (c | x) given that a ? b | x : c even is not a valid expression? This does not look like an intentional design decision, more like a mistake (bug).
The natural expectation is that the pipe in the end of an expression should be applied to the whole expression, even if there is no parentheses. According to the docs, pipes are a way to write display-value transformations that you can declare in your HTML. They are perceived as external to expressions, something that modifies the expression without really being part of it. For this intuition to be valid, pipes must have the lowest precedence. The current behavior breaks the intuition for no reason, without adding any value.
Activity
Mapache commentedon Dec 3, 2018
The behavior you describe for AngularJS looks like the bug, as the | operator is supposed to have higher precedence than ?: even in plain JavaScript.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
Personally, I recommend using explicit grouping when chaining lots of operators together, as a form of executable documentation that makes programmer intent clear instead of forcing the reader to rely on their memory of precedence between distinct families of operators.
thorn0 commentedon Dec 3, 2018
The
|operator in JS has nothing to do with the|operator in Angular expressions.trotyl commentedon Dec 4, 2018
Pipe in template is an equivalent of JavaScript pipeline operator in semantic, the Angular behavior is correct, where
a ? b : c | xmeansa ? b : (c | x).thorn0 commentedon Dec 4, 2018
@trotyl
a ? b | x : ca valid expression then?|>might be standardized and become really widespread, people will get used to its precedence, so the precedence of our|might become confusing'? I would buy this justification if Angular's operator looked the same (|>). But it doesn't look the same, why would anybody expect it to have the same precedence?trotyl commentedon Dec 4, 2018
@thorn0
b | x : ccould be recognized as pipexwith additional pipe parameterc. There may need to be some better error handling, but it's the syntax ambiguity rather than precedence issue.Pipeis a syntax sugar for function calls with better ergonomics, which is equivalent to JavaScript pipeline operator. The template language is a JavaScript subset with additional template utils, there's no reason to violates JavaScript deliberately if already conforming.gkalpak commentedon Dec 4, 2018
TBH, I personally find that Angular's
|has enough differences with|>anyway (e.g. appearance 😁, order of arguments), that keeping one characteristic in sync (precedence) in the name of "mental model equivalence" is a weak argument. (Even more so that JS already has a|operator with totally different semantics, so we've missed the "reasonable equivalence" train, I'm afraid 😛).In my mind, Angular's
|is more like UNIX pipes and in that sense I would also expect them to have lower precedence (from a mental model pov).m2c
FWIW, I would always parenthesize such complex expressions, regardless of the precedences 😉
trotyl commentedon Dec 4, 2018
@gkalpak Have had a check with the bash operator precedence, where pipe do have higher precedence than logical operators (
&&or||, sadly there's no?:in bash):Would be parsed as
rather than
thorn0 commentedon Dec 4, 2018
@trotyl And what about
a | x ? b : c? My point abouta ? b | x : cis that it is inconsistent. If we want to apply a pipe to some operand ofa ? b : c, why do we have to parenthesizeaandb, but notc?Normally, if an operator
O1has a higher precedence than the operatorO2it means that we can use expressions withO1as operands ofO2without parentheses. It's almost not the case for Angular's|and?:. So it's a really strange precedence choice, I must conclude.trotyl commentedon Dec 4, 2018
@thorn0 It's just a parser implementation bug unrelated to ternary operator, even
a | x + 1would produce same error. The current scenario is that the left-hand side of pipe can be any expression, while right-hand side must be purely pipe name with optional pipe parameters.The current Angular template parser is just a poorly hand-written recursive descent implementation, any issue is expected to happen.
EDIT: checked pipeline operator,
it should be correct one,a |> x + 1would be translated tovar _a; (_a = a, (x + 1)(_a)), meaning that whole right-hand side is considered to be the function to invoke. But Angular pipe cannot be dynamically computed, so the restriction make sense.EDIT2: checked again,
a |> x ? b : cwould becomevar _a; (_a = a, x(_a)) ? b : c;, which is correctly handled (ternary having lower precedence), still seems to be an Angular bug.mhevery commentedon Dec 4, 2018
Yes, you are right the precedence is wrong :-(
3 remaining items
[-]Pipes vs ternaries: unexpected grammar difference between Angular and AngularJS[/-][+]Pipe (`|`) operator has incorrect precedence (too tight)[/+]petebacondarwin commentedon Oct 15, 2021
This is being tracked in the aggregate issue of #43485 for which we need to create a project proposal.
jelbourn commentedon Jul 10, 2024
Duplicate of #43485
Closing this as a duplicate of #43485 even though they're not exactly the same thing because it's the ultimate direction things will likely move. At this point, we think it's far too breaking of a change to change the operator precedence for pipes. Any changes here would be part of a much larger (and hypothetical) shift in the way Angular template expressions work.
angular-automatic-lock-bot commentedon Aug 10, 2024
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.