Repository: prettier/prettier (JavaScript)
Date: 2018-02-09 14:38:38+00:00
Task type: Bug Fix

Issue:
ambiguity on ternary and flow types
**Prettier 1.10.2**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuc0DOMAEAzCFMC8mAFMQIwD8ATEgMwCUSmUArgLYBGcATvQNwgANCAgAHGAEt0yUAENu3CAHcACvIRpkIWQDcIEgCZDtGZNlkAbNHGEdussAGs4MAMqiHEqAHNkMbiw2IAYQYGaW1sJe1twwKvbebLLhVkEAVmgAHgBC9k4urrJscAAyXnApkSIsMKI1VJVBHtwxWtgWysai3F4wAOqGMAAWyAAcAAzC3RDWffaiWt1wMToVwtxwAI4sEhvxsonJSOapwtZsEn4BQWhe3hZwAIosEPCNwjCyHAMGw8hUH3sEgsdwAwhA2EktFBoGsQCxrAAVL6aY4ROAAXwxQA)
```sh
--parser flow
```

**Input:**
```jsx
const foo = ((1?2:3): number);
```

**Output:**
```jsx
const foo = (1 ? 2 : 3: number);

```

**Expected behavior:**

I find the output very confusing.  It reads to me as `1 ? 2 : (3: number)` but it means `((1 ? 2 : 3): number)`


Issue discussion:
Thanks for the issue! I think we can bake this one into #3850.
propose re-opening since #3850 is a different issue in my opinion as it doesn't involve flow/ts types.  If you really feel it belongs in the same place for eng reasons or whatnot I'll comment over there.
Both are about printing parens around the "else-part" of ternaries when the "else-part" is another ternary?
But it's not another ternary in this case, it's a static type.  And I'm suggesting parens around the entire ternary so that the type binding is clear
@lydell seems, it is other issue and not related to link on issue above, let's reopen to discussion
Happens in Babylon, too:

**Prettier 1.10.2**
[Playground link](https://prettier.io/playground/#N4Igxg9gdgLgprEAuc0DOMAEAzCFMC8mAFMQIwD8ATEgMwCUSmUArgLYBGcATvQNwgANCAgAHGAEt0yUAENu3CAHcACvIRpkIWQDcIEgCZDtGZNlkAbNHGEdussAGs4MAMqiHEqAHNkMbiw2IAYQYGaW1sJe1twwKvbebLLhVkEAVmgAHgBC9k4urrJscAAyXnApkSIsMKI1VJVBHtwxWhyyHACeFtDGotxeMADqhjAAFsgAHAAMwv0Q1kP2olr9cDE6FcLccACOLBI78bKJyUjmqcLWbBJ+AUFoXt4WcACKLBDwjcIwHSMG42QVB+9gkFieAGEIGwklooNAtiAWNYACodTTnCJwAC+2KAA)

**Input:**
```jsx
const foo = ((1?2:3): number);
```

**Output:**
```jsx
const foo = (1 ? 2 : 3: number);

```
Haha, it is indeed confusing since it fooled me so thoroughly!
@lydell Should I check if the `TypeCastExpression`’s child is a `ConditionalExpression` or if the `ConditionalExpression`’s parent is a `TypeCastExpression`?
@j-f1 I don't know. I'd probably check some other cases where we _sometimes_ print parens and try to use the same approach.

Solution patch:
diff --git a/src/common/fast-path.js b/src/common/fast-path.js
index 6e047acd48bb..6f1db155a9ed 100644
--- a/src/common/fast-path.js
+++ b/src/common/fast-path.js
@@ -554,6 +554,7 @@ FastPath.prototype.needsParens = function(options) {
         case "AwaitExpression":
         case "JSXSpreadAttribute":
         case "TSTypeAssertionExpression":
+        case "TypeCastExpression":
         case "TSAsExpression":
         case "TSNonNullExpression":
           return true;


Test patch:
diff --git a/tests/flow_type_cast/__snapshots__/jsfmt.spec.js.snap b/tests/flow_type_cast/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
index 000000000000..a413b4477a2d
--- /dev/null
+++ b/tests/flow_type_cast/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,25 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`expression.js 1`] = `
+let x: string = (foo: string);
+
+// https://github.com/prettier/prettier/issues/3936
+const foo = ((1?2:3): number);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+let x: string = (foo: string);
+
+// https://github.com/prettier/prettier/issues/3936
+const foo = ((1 ? 2 : 3): number);
+
+`;
+
+exports[`statement.js 1`] = `
+foo: string;
+bar: number;
+(foo.bar: SomeType);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+foo: string;
+bar: number;
+(foo.bar: SomeType);
+
+`;
diff --git a/tests/flow_type_cast/expression.js b/tests/flow_type_cast/expression.js
new file mode 100644
index 000000000000..50ecacd508da
--- /dev/null
+++ b/tests/flow_type_cast/expression.js
@@ -0,0 +1,4 @@
+let x: string = (foo: string);
+
+// https://github.com/prettier/prettier/issues/3936
+const foo = ((1?2:3): number);
diff --git a/tests/flow_type_cast/jsfmt.spec.js b/tests/flow_type_cast/jsfmt.spec.js
new file mode 100644
index 000000000000..c1ba82f46794
--- /dev/null
+++ b/tests/flow_type_cast/jsfmt.spec.js
@@ -0,0 +1,1 @@
+run_spec(__dirname, ["flow", "babylon"]);
diff --git a/tests/flow_type_cast/statement.js b/tests/flow_type_cast/statement.js
new file mode 100644
index 000000000000..0dc735b4ac4c
--- /dev/null
+++ b/tests/flow_type_cast/statement.js
@@ -0,0 +1,3 @@
+foo: string;
+bar: number;
+(foo.bar: SomeType);