Skip to content

[bug] JSX parsing fails with spurious syntax errors in ternary expression with nested JSX and multi-property object literals #2936

@hou-pu

Description

@hou-pu

Bug Report

tsgo version

7.0.0-dev.20260227.1

Reproduction

This is a fully self-contained reproduction with no external dependencies.

tsconfig.json:

{
  "compilerOptions": {
    "jsx": "preserve",
    "noEmit": true
  }
}

repro.tsx:

import { memo } from 'react'

const HoverCardText = (p: { label: any; text: any; className?: string }) => null
const DEFAULT_NULL_VALUE = '--'
const t = (key: string, params?: Record<string, any>) => key
const nf = (v: any, opts: { precision: number; rounding: string }) => String(v)

export const Example = memo(function Example() {
  const isLogin = true

  return (
    <div>
      <div>{t('label')}</div>
      {!isLogin ? (
        DEFAULT_NULL_VALUE
      ) : (
        <HoverCardText
          className="test"
          label={
            <div>
              {t('some.key', {
                s1: nf(1, { precision: 2, rounding: 'down' }),
                s2: nf(2, { precision: 2, rounding: 'down' }),
              })}
            </div>
          }
          text={
            <div>
              {nf(0, { precision: 2, rounding: 'down' })} USDT
            </div>
          }
        ></HoverCardText>
      )}
    </div>
  )
})

Expected behavior

No syntax errors — the JSX is valid. Standard tsc (5.x) compiles this without any syntax issues (only reports the expected TS2307: Cannot find module 'react' error since React isn't installed).

Actual behavior

tsgo --noEmit reports 30 spurious syntax errors starting at the <HoverCardText JSX element, such as:
repro.tsx(18,11): error TS1005: ',' expected
repro.tsx(19,11): error TS1005: ',' expected
repro.tsx(21,15): error TS1005: '(' expected
repro.tsx(21,18): error TS1003: Identifier expected....
The parser appears to fail to recognize the JSX context and instead interprets JSX attributes as JavaScript object properties.

Key observations from investigation

Removing any one of these elements makes the bug disappear:
The ternary expression (? ... : ...)
The

{t('label')}
preceding the ternary
The second property in the object literal inside label (s2: nf(...))
Reducing the object literal to a single property inside the label JSX attribute makes it work.
Using a string literal ('--') instead of DEFAULT_NULL_VALUE in the ternary's truthy branch also makes it work.
tsc 5.x handles this code correctly in all cases.
The bug appears to involve the parser's JSX state management when processing deeply nested expressions (ternary → JSX → JSX attribute → JSX child → function call → object literal with multiple properties containing nested object literals).

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions