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

Argument of type '() => void' is not assignable to parameter of type '() => Chainable<any>'. #18915

Closed
erwinheitzman opened this issue Nov 15, 2021 · 19 comments
Labels
stage: needs review The PR code is done & tested, needs review type: typings Issue related to Cypress types (for TypeScript)

Comments

@erwinheitzman
Copy link

erwinheitzman commented Nov 15, 2021

Current behavior

With the upgrade to v9, Cypress is reporting the following error when adding a custom method:

Argument of type '() => void' is not assignable to parameter of type '() => Chainable<any>'.

Desired behavior

According to the documentation, no other code should be needed to make this work.

Thus I believe that void should be a valid type to be supported.

Test code to reproduce

Cypress.Commands.add('login', () => {
  // do something
})

Cypress Version

9.0.0

Other

No response

@danielhusar
Copy link

danielhusar commented Nov 15, 2021

I have the same issue, but with callback having arguments:

Cypress.Commands.add('mockApi', ({ user = {} }) => {
  ...
})

@michaeljaltamirano
Copy link

michaeljaltamirano commented Nov 15, 2021

@erwinheitzman I think you need to add the custom method to Chainable as described in the following documentation: https://github.com/cypress-io/cypress-example-todomvc#custom-commands, e.g.

/// <reference types="cypress" />

declare namespace Cypress {
  interface Chainable {
    login(): void
  }
}

See also: https://docs.cypress.io/guides/tooling/typescript-support#Types-for-custom-commands

@erwindetesters
Copy link

That is to get the commands recognised in your tests, however in this case the internal types do not seem correct instead @michaeljaltamirano

@aomader
Copy link

aomader commented Nov 16, 2021

This behavior has been adjusted in #17496

Now you have to add correct types for your custom commands to Chainable.

However, I was under the impression that a custom command does not have to return a Chainable, as this is handled by cypress itself correctly. This was also suggested by the previous CanReturnChainable return type of the command function to add.

Is this assumption incorrect? @remcohaszing

If this still holds, the PR is not correct and should be updated.

@erwindetesters
Copy link

I see, seems I misunderstood the changes when reading the PR and changelog. I will try again later today and I'm assuming this will then be resolved.

@remcohaszing
Copy link
Contributor

I think this is a bug in #17496. I can fix this.

Just to make sure before I fix it, it should be like this right?

declare global Chainable {
  foo(bar: string): Chainable<string>;
}

Cypress.Commands.add('foo', (bar) => {
  // $ExpectType string
  bar;
  // Returning a string is ok
  return 'ok';
  // Returning a chainable wrapping a string is also ok
  return cy.hash();
});

it('should work', () => {
  // $ExpectType Chainable<string>
  cy.foo('asd');
});

@aomader
Copy link

aomader commented Nov 17, 2021

Looking at CanReturnChainable, I would assume this is correct. But a cypress guy might jump in here.

@shazaddad
Copy link

@mateustalles
Copy link

mateustalles commented Nov 17, 2021

@remcohaszing Hi I'm a Cypress guy. The point is we shouldn't be required to return anything from the commands at commands.ts. They don't return any direct value nor can be assigned to variables. Only yields the same that the Cypress command does

declare namespace Cypress {
    interface Chainable {
      /**
       * Custom command to select DOM element by data-cy attribute with timeout per ms
       * @example cy.dataCy('greeting', { timeout: 50000 })
       */
      dataCy(value: string, timeout?: number): Chainable<Element>
  }
}

Cypress.Commands.add('dataCy', (value, timeout) => {
  cy.get(`[data-cy="${value}"]`, { timeout })
})

/// spec.ts
cy.dataCy('this-element').then($el => $el.show())

Also adding a return before the cy.get command doesn't solve the issue.

@cypress-bot cypress-bot bot added stage: needs review The PR code is done & tested, needs review stage: work in progress and removed stage: needs review The PR code is done & tested, needs review stage: work in progress labels Nov 17, 2021
@erwindetesters
Copy link

erwindetesters commented Nov 19, 2021

Hey all, for me the issue was resolved after changing the types as suggested by @michaeljaltamirano and @aomader like so:

// cypress/support/index.d.ts

declare namespace Cypress {
  interface Chainable {
    login(): void
  }
}

If anyone is still having issues, please create an issue specific to your issue as it seems like this can be closed (which I will sometime this weekend if there are no serious objections) so the devs don't have to go through the whole ticket to find what information is relevant and what is not.

@erwindetesters
Copy link

erwindetesters commented Nov 22, 2021

Apparently I cannot close it myself but note to the maintainers, this can be closed.

I think it would make sense for people to be able to close their own tickets, might be something to consider.

@cypress-bot cypress-bot bot added stage: work in progress stage: needs review The PR code is done & tested, needs review and removed stage: needs review The PR code is done & tested, needs review stage: work in progress labels Nov 22, 2021
@bahmutov bahmutov reopened this Nov 23, 2021
@cypress-bot cypress-bot bot added stage: work in progress stage: needs review The PR code is done & tested, needs review and removed stage: needs review The PR code is done & tested, needs review stage: work in progress labels Nov 23, 2021
@akshayhiremath9731
Copy link

akshayhiremath9731 commented Feb 1, 2022

Cypress.Commands.add('path', (text: string) => {
cy.xpath("(//span[contains(.,'" + text + "')]/following::td)[1]");
});

interface Chainable {
path(text: string): void;
}

while using
cy.path('paragraphText').clear().

i am getting this error
Property 'clear' does not exist on type 'void'
@remcohaszing

@emilyrohrbough emilyrohrbough added the type: typings Issue related to Cypress types (for TypeScript) label Feb 1, 2022
@flotwig
Copy link
Contributor

flotwig commented Feb 1, 2022

@bahmutov did you intend to reopen this issue? I thought #18967 fixes this

@flotwig
Copy link
Contributor

flotwig commented Feb 8, 2022

Closing since #18967 should have fixed this. Please open a new issue if this is still broken in the latest Cypress.

@flotwig flotwig closed this as completed Feb 8, 2022
Yohandah added a commit to Yohandah/cypress-example-recipes that referenced this issue Feb 24, 2022
See : cypress-io/cypress#18915

An error 'Argument of type '() => void' is not assignable to parameter of type '() => Chainable<any>' throws when you return directly

cypress-io/cypress#18915 (comment)

fixes cypress-io#763
@LuisValgoi
Copy link

Same thing here...

image

Screen Shot 2022-03-30 at 13 34 57

@alexzavg
Copy link

same as above comment^^^

@mleblancbpa
Copy link

If anybody else falls here to find out how to get rid of typescript error in declaring commands, you have to wrap your declare namespace Cypress bloc in a declare global { ... } block like so:

declare global {
  namespace Cypress {
    interface Chainable {
      login(): void;
    }
  }
}

@ReddixT
Copy link

ReddixT commented Dec 7, 2022

This still doesn't fix the issue. The datacy command works but it still shows this error.
image

@lflucasferreira
Copy link

Same page here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stage: needs review The PR code is done & tested, needs review type: typings Issue related to Cypress types (for TypeScript)
Projects
None yet
Development

Successfully merging a pull request may close this issue.