Repository: babel/babel
File: packages/babel-parser/src/plugins/typescript/index.ts (TypeScript)

Code before:
    parseConditional(
      expr: N.Expression,

      startLoc: Position,
      refExpressionErrors?: ExpressionErrors | null,
    ): N.Expression {
      if (!this.match(tt.question)) return expr;

      if (this.state.maybeInArrowParameters) {
        const nextCh = this.lookaheadCharCode();
        // These tokens cannot start an expression, so if one of them follows
        // ? then we are probably in an arrow function parameters list and we
        // don't parse the conditional expression.
        if (
          nextCh === charCodes.comma || // (a?, b) => c
          nextCh === charCodes.equalsTo || // (a? = b) => c
          nextCh === charCodes.colon || // (a?: b) => c
          nextCh === charCodes.rightParenthesis // (a?) => c
        ) {
          /*:: invariant(refExpressionErrors != null) */
          this.setOptionalParametersError(refExpressionErrors!);
          return expr;
        }
      }

      this.expect(tt.question);
      const node = this.startNodeAt<N.ConditionalExpression>(startLoc);
      node.test = expr;
      // While parsing the consequent, set a flag to prevent treating
      // `:` as an arrow return type annotation. In `a ? async(b) : c`,
      // the `:` is the ternary separator, not a return type annotation.
      const oldInConditionalConsequent = this.state.inConditionalConsequent;
      this.state.inConditionalConsequent = true;
      node.consequent = this.parseMaybeAssignAllowIn();
      this.state.inConditionalConsequent = oldInConditionalConsequent;
      this.expect(tt.colon);
      node.alternate = this.parseMaybeAssign();
      return this.finishNode(node, "ConditionalExpression");
    }

    // Note: These "type casts" are *not* valid TS expressions.
    // But we parse them here and change them when completing the arrow function.
    parseParenItem<T extends N.Expression | N.RestElement | N.SpreadElement>(
      node: T,
      startLoc: Position,
    ): T | N.TsTypeCastExpression {
      const newNode = super.parseParenItem(node, startLoc);
      if (this.eat(tt.question)) {
        (newNode as N.Identifier).optional = true;
        // Include questionmark in location of node
        // Don't use this.finishNode() as otherwise we might process comments twice and

Review comment (suggestion):
```suggestion
      this.next(); // eat `?`
```
Since we already tested `tt.question` at the very start of this function.

Code after:
      if (!this.match(tt.question)) return expr;

      if (refExpressionErrors != null) {
        const nextCh = this.lookaheadCharCode();
        // These tokens cannot start an expression, so if one of them follows
        // ? then we are probably in an arrow function parameters list and we
        // don't parse the conditional expression.
        if (
          nextCh === charCodes.comma || // (a?, b) => c
          nextCh === charCodes.equalsTo || // (a? = b) => c
          nextCh === charCodes.colon || // (a?: b) => c
          nextCh === charCodes.rightParenthesis // (a?) => c
        ) {
          this.setOptionalParametersError(refExpressionErrors);
          return expr;
        }
      }

      this.next(); // eat `?`
      const node = this.startNodeAt<N.ConditionalExpression>(startLoc);
      node.test = expr;
      // While parsing the consequent, set a flag to prevent treating
      // `:` as an arrow return type annotation. In `a ? async(b) : c`,
      // the `:` is the ternary separator, not a return type annotation.
      const oldInConditionalConsequent = this.state.inConditionalConsequent;
      this.state.inConditionalConsequent = true;
      node.consequent = this.parseMaybeAssignAllowIn();
      this.state.inConditionalConsequent = oldInConditionalConsequent;
      this.expect(tt.colon);
      node.alternate = this.parseMaybeAssign();
      return this.finishNode(node, "ConditionalExpression");
    }

    // Note: These "type casts" are *not* valid TS expressions.
    // But we parse them here and change them when completing the arrow function.
    parseParenItem<T extends N.Expression | N.RestElement | N.SpreadElement>(
      node: T,
      startLoc: Position,
    ): T | N.TsTypeCastExpression {
      const newNode = super.parseParenItem(node, startLoc);
      if (this.eat(tt.question)) {
        (newNode as N.Identifier).optional = true;
        // Include questionmark in location of node
        // Don't use this.finishNode() as otherwise we might process comments twice and
        // include already consumed parens
        this.resetEndLocation(node);
      }

      if (this.match(tt.colon)) {
        const typeCastNode = this.startNodeAt<N.TsTypeCastExpression>(startLoc);
        typeCastNode.expression = node as N.Expression;