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

Bound functions for find* queries throw error in typescript when waitForElementOptions argument is supplied. #291

Closed
le0nik opened this issue Jun 20, 2019 · 1 comment

Comments

@le0nik
Copy link

le0nik commented Jun 20, 2019

  • dom-testing-library version: 5.2.1
  • react-testing-library version: 8.0.1
  • react version: 16.8.6
  • node version: 10.16.0
  • npm (or yarn) version: npm(6.9.0), yarn(1.16.0)

Relevant code or config:

const { findByText } = render(<App />);
const button = await findByText( // TS error: "Expected 1-2 arguments, but got 3"
  /inc/i,
  {},
  {
    timeout: 100
  }
);

What you did:

Used bound findByText function returned by render from @testing-library/react with waitForElementOptions argument.

What happened:

Typescript threw an error Expected 1-2 arguments, but got 3

Reproduction:

https://codesandbox.io/s/uok74

Take a look at App.test.tsx.

Problem description:

waitForElementOptions argument is not considered for bound functions type here:

export type BoundFunction<T> = T extends (
attribute: string,
element: HTMLElement,
text: infer P,
options: infer Q,
) => infer R
? (text: P, options?: Q) => R
: T extends (a1: any, text: infer P, options: infer Q) => infer R
? (text: P, options?: Q) => R
: never

Suggested solution:

Another signature should be added that supports waitForElementOptions argument to the type linked above.

I tried to do that, but my attempt failed. Here's what I've tried:

export type BoundFunction<T> = T extends (
  attribute: string,
  element: HTMLElement,
  text: infer P,
  options: infer Q,
) => infer R
  ? (text: P, options?: Q) => R
  : T extends (a1: any, text: infer P, options: infer Q, waitForElementOptions: infer S) => infer R
  ? (text: P, options?: Q, waitForElementOptions?: S) => R
  : T extends (a1: any, text: infer P, options: infer Q) => infer R
  ? (text: P, options?: Q) => R
  : never

Note these 2 lines that I've added:

: T extends (a1: any, text: infer P, options: infer Q, waitForElementOptions: infer S) => infer R
? (text: P, options?: Q, waitForElementOptions?: S) => R

It fixed the case with bound find* queries, now they accept waitForElementOptions argument, but it breaks proper typechecking for get* and other bound queries, that accept fewer arguments. For some reason typescript uses this signature for them too, which results in ability to call them with more arguments than they accept.

Example:

const { getByText } = render(<App />);
const button = getByText( // TS should throw error here, but doesn't
  /inc/i,
  {},
  {
    timeout: 100
  }
);

I probably don't fully understand how assignability rules work for function signatures in conditional types in Typescript(I think it should be from top to bottom, from more to less specific signatures). Would be great if someone could find a solution to this.

@le0nik le0nik changed the title bound function for find* methods throws error in typescript Bound functions for find* queries throw error in typescript when waitForElementOptions argument is supplied. Jun 20, 2019
@le0nik
Copy link
Author

le0nik commented Jun 20, 2019

Just found out that it's a duplicate of this 2 month old issue in a different repo: testing-library/react-testing-library#366. I'll close this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant