Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different inference behaviour between JSX and function call with context sensitive functions. #50121

Closed
Mike-Dax opened this issue Aug 1, 2022 · 4 comments
Labels
Experience Enhancement Noncontroversial enhancements Help Wanted You can do this Suggestion An idea for TypeScript
Milestone

Comments

@Mike-Dax
Copy link

Mike-Dax commented Aug 1, 2022

Bug Report

🔎 Search Terms

type inference function arguments, context sensitive function inference

🕗 Version & Regression Information

This is the behaviour in both 4.7.4 and 4.8.0 beta, none of the cases worked before 4.7.

This seems related to #48538

⏯ Playground Link

Playground link with relevant code

💻 Code

interface GlobalState {
  key: number
}

interface ComponentProps<T> {
  accessor: (state: GlobalState) => T
  mutator?: (staging: GlobalState, value: T) => void
}

export function Component<T>(props: ComponentProps<T>) {
  return null
}

// This works
const functionCall1 = Component({
  accessor: state => state.key,
  mutator: (state, value) => {
    state.key = value
  },
})

// This fails 
const functionCall2 = Component({
  mutator: (state, value) => {
    state.key = value
  },
  accessor: state => state.key,
})

// I would expect this to work but it doesn't
const componentCall1 = (
  <Component
    accessor={state => state.key}
    mutator={(state, value) => {
      state.key = value
    }}
  />
)

// This fails 
const componentCall2 = (
  <Component
    mutator={(state, value) => {
      state.key = value
    }}
    accessor={state => state.key}
  />
)

Note that jsx is set to preserve.

🙁 Actual behavior

state.key = value fails with Type 'unknown' is not assignable to type 'number'.(2322)

const componentCall1 = (
  <Component
    accessor={state => state.key}
    mutator={(state, value) => {
      state.key = value
    }}
  />
)

The Component<T> is inferred to be Component<unknown>

🙂 Expected behavior

I would expect it to type check the same as functionCall1

const functionCall1 = Component({
  accessor: state => state.key,
  mutator: (state, value) => {
    state.key = value
  },
})

I'd expect Component<T> to be inferred to be Component<number>

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Help Wanted You can do this Experience Enhancement Noncontroversial enhancements labels Aug 2, 2022
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Aug 2, 2022
@RyanCavanaugh
Copy link
Member

Anders did some work to make context-sensitive functions in object literals behave better in inference in 4.7, but the JSX code is a separate codepath. The work here would be to "copy" that logic over into the JSX behavior.

@Mike-Dax
Copy link
Author

Mike-Dax commented Mar 5, 2023

Would you be able to point me in the direction of that JSX codepath? Perhaps there's enough context from the linked PR and that code for me to replicate that logic across.

@Andarist
Copy link
Contributor

This was fixed by #52837

@Mike-Dax
Copy link
Author

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Experience Enhancement Noncontroversial enhancements Help Wanted You can do this Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants