cypress icon indicating copy to clipboard operation
cypress copied to clipboard

Improve typescript types of cy.wrap

Open WIStudent opened this issue 4 years ago • 7 comments
trafficstars

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

WIStudent avatar Sep 21 '21 15:09 WIStudent

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>;
    }
  }
}

lucaciraolo avatar Mar 28 '23 13:03 lucaciraolo

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 avatar Sep 25 '23 01:09 cypress-app-bot

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)
  })
}

mikavilpas avatar Oct 01 '23 07:10 mikavilpas

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 avatar Mar 31 '24 01:03 cypress-app-bot

This issue has been closed due to inactivity.

cypress-app-bot avatar Apr 14 '24 01:04 cypress-app-bot

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

alperen-bircak avatar Aug 14 '24 11:08 alperen-bircak

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 avatar Feb 11 '25 01:02 cypress-app-bot

This issue has been closed due to inactivity.

cypress-app-bot avatar Feb 25 '25 02:02 cypress-app-bot