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

Improve typescript types of cy.wrap #18182

Open
WIStudent opened this issue Sep 21, 2021 · 6 comments
Open

Improve typescript types of cy.wrap #18182

WIStudent opened this issue Sep 21, 2021 · 6 comments
Labels
type: typings Issue related to Cypress types (for TypeScript)

Comments

@WIStudent
Copy link

What would you like?

When using cy.wrap with a Promise the resulting type currently does not get inferred automatically. Instead generics need to be passed explicitly.

const getNumber = async (): Promise<number> => 42;

cy.wrap(getNumber()).then(n => {
  // n: unknown
});

cy.wrap<Promise<number>, number>(getNumber()).then(n => {
  // n: number
});

I think this is a bit inconvenient, typescript should be able to infer the type from the promise without needing to pass the generics. Take a look at the current type definitions of cy.wrap:

interface Chainable<Subject = any> {
  wrap<E extends Node = HTMLElement>(element: E | JQuery<E>, options?: Partial<Loggable & Timeoutable>): Chainable<JQuery<E>>
  wrap<F extends Promise<S>, S>(promise: F, options?: Partial<Loggable & Timeoutable>): Chainable<S>
  wrap<S>(object: S, options?: Partial<Loggable & Timeoutable>): Chainable<S>
}

By combining the second and third overload typescript is able to infer the type automatically:

interface Chainable<Subject = any> {
  wrap<E extends Node = HTMLElement>(element: E | JQuery<E>, options?: Partial<Loggable & Timeoutable>): Chainable<JQuery<E>>
  wrap<S>(object: S | Promise<S>, options?: Partial<Loggable & Timeoutable>): Chainable<S>
}

This introduces a breaking change for anyone who is currently passing the Promise generics explicitly (they would need to remove those generics), but in return it simplifies the use of cy.wrap with Promises in typescript greatly.

Why is this needed?

No response

Other

No response

@sainthkh sainthkh added type: typings Issue related to Cypress types (for TypeScript) stage: ready for work The issue is reproducible and in scope and removed stage: ready for work The issue is reproducible and in scope labels Oct 4, 2021
@lucaciraolo
Copy link

In case anyone else wants to get automatic typescript inferring for wrap, you can just add @WIStudent's improved cy.wrap definition to your cypress/support/index.ts file

// cypress/support/index.ts
declare global {
  namespace Cypress {
    interface Chainable {
      wrap<E extends Node = HTMLElement>(
        element: E | JQuery<E>,
        options?: Partial<Loggable & Timeoutable>,
      ): Chainable<JQuery<E>>;
      wrap<S>(
        object: S | Promise<S>,
        options?: Partial<Loggable & Timeoutable>,
      ): Chainable<S>;
    }
  }
}

@cypress-app-bot
Copy link
Collaborator

This issue has not had any activity in 180 days. Cypress evolves quickly and the reported behavior should be tested on the latest version of Cypress to verify the behavior is still occurring. It will be closed in 14 days if no updates are provided.

@cypress-app-bot cypress-app-bot added the stale no activity on this issue for a long period label Sep 25, 2023
@mikavilpas
Copy link

mikavilpas commented Oct 1, 2023

I created a simple typecheck test case to prove the workaround works.

// cypress/support/commands.ts

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

declare global {
  namespace Cypress {
    // https://github.com/cypress-io/cypress/issues/18182#issuecomment-1486921299
    interface Chainable {
      wrap<E extends Node = HTMLElement>(
        element: E | JQuery<E>,
        options?: Partial<Loggable & Timeoutable>,
      ): Chainable<JQuery<E>>
      wrap<S>(
        object: S | Promise<S>,
        options?: Partial<Loggable & Timeoutable>,
      ): Chainable<S>
    }
  }
}

// Test function: if this compiles, the workaround works.
// Comment the above workaround out to see it fail, remove the comments to see it pass again
const testWrap = (): void => {
  const getNumber = async (): Promise<number> => 42
  cy.wrap(getNumber()).then((n) => {
    // n: number
    console.log(n + n)
  })
}

@cypress-app-bot cypress-app-bot removed the stale no activity on this issue for a long period label Oct 2, 2023
@cypress-app-bot
Copy link
Collaborator

This issue has not had any activity in 180 days. Cypress evolves quickly and the reported behavior should be tested on the latest version of Cypress to verify the behavior is still occurring. It will be closed in 14 days if no updates are provided.

@cypress-app-bot cypress-app-bot added the stale no activity on this issue for a long period label Mar 31, 2024
@cypress-app-bot
Copy link
Collaborator

This issue has been closed due to inactivity.

@cypress-app-bot cypress-app-bot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 14, 2024
@alperen-bircak
Copy link

This issue does not deserve to be closed, essential for DX

@jennifer-shehane jennifer-shehane removed the stale no activity on this issue for a long period label Aug 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: typings Issue related to Cypress types (for TypeScript)
Projects
None yet
Development

No branches or pull requests

7 participants