Skip to content

TS2488: Generic type parameter not inferred from JSX props, falls back to default #2797

@theoludwig

Description

@theoludwig

tsgo reports a false positive TS2488 when using a generic JSX component where a type parameter should be inferred from one prop (selector) and consumed in another (children).

tsgo fails to infer the type parameter from the JSX prop and falls back to the default, causing a spurious error. The equivalent non-JSX function call works correctly.

tsc (TypeScript 5.9.3) reports no error on the same code.

Minimal Reproduction

https://github.com/theoludwig/oxlint-tsgolint-issue-135

interface State {
  value: boolean
}

declare const Subscribe: <TSelected = State>(props: {
  selector?: (state: State) => TSelected
  children: (state: TSelected) => void
}) => React.ReactNode

const _result = (
  <Subscribe
    selector={(state) => {
      return [state.value]
    }}
  >
    {([value = false]) => {
      console.log(value)
    }}
  </Subscribe>
)

Expected behavior

TSelected should be inferred as boolean[] from the selector return type (same as tsc). No error should be reported.

Actual behavior

tsgo does not infer TSelected from the selector prop and falls back to the default (State). This causes:

TS2488: Type 'State' must have a '[Symbol.iterator]()' method that returns an iterator.

on the array destructuring pattern [value = false] in children.

Key observation: JSX-specific

The same pattern as a regular function call works correctly in tsgo, no error:

Subscribe({
  selector: (state) => {
    return [state.value]
  },
  children: ([value = false]) => {
    console.log(value)
  },
})

The bug only manifests when the generic function is used as a JSX component with children passed as JSX children (between opening and closing tags) rather than as a direct prop.

Environment

  • Detected via oxlint 1.48.0 with --type-check --type-aware (which uses tsgo via oxlint-tsgolint 0.14.0)
  • tsc (TypeScript 5.9.3): no error
  • This issue was not present with oxlint-tsgolint 0.12.2 and appeared after 0.13.0 which updated the typescript-go submodule

Real-world impact

This affects all uses of @tanstack/react-form's form.Subscribe component, which uses exactly this pattern — a selector prop that transforms FormState into a derived value, and children that receives the selected value.

Metadata

Metadata

Assignees

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