Search code examples
javascripttypescriptcypresstypescript-types

How to attach data type to Cypress.as alias function


I have an object out of which I create an alias named userId

cy.wrap(response.id).as('userId');

When referencing userId its type is JQuery<HTMLElement>

cy.get('@userId').then(userId => // userId type is JQuery<HTMLElement> });

How does one define the alias type when defining the alias?

Intention is to have it as a number directly instead of default JQuery<HTMLElement>

EDIT

I do not want something like this

cy.get<number>('@userId').then(userId => // userId type is number });

I want to define the type at function definition.


Solution

  • The problem is with these two type defns in cypress.d.ts

    // cypress.d.ts
    
    /**
     * Get one or more DOM elements by selector.
     * The querying behavior of this command matches exactly how $(…) works in jQuery.
     * @see https://on.cypress.io/get
     * @example
     *    cy.get('.list>li')    // Yield the <li>'s in <.list>
     *    cy.get('ul li:first').should('have.class', 'active')
     *    cy.get('.dropdown-menu').click()
     */
    get<E extends Node = HTMLElement>(
      selector: string, 
      options?: Partial<Loggable & Timeoutable & Withinable & Shadow>)
      : Chainable<JQuery<E>>
    
    /**
     * Get one or more DOM elements by alias.
     * @see https://on.cypress.io/get#Alias
     * @example
     *    // Get the aliased ‘todos’ elements
     *    cy.get('ul#todos').as('todos')
     *    //...hack hack hack...
     *    //later retrieve the todos
     *    cy.get('@todos')
     */
    get<S = any>(
      alias: string, 
      options?: Partial<Loggable & Timeoutable & Withinable & Shadow>)
      : Chainable<S>
    
    

    You can "fix" it by reversing the order,

    // cypress/support/index.ts
    
    declare global {
      namespace Cypress {
        interface Chainable<Subject> {
          // change the order of these two dfns
          get<S = any>(alias: string, options?: Partial<Loggable & Timeoutable & Withinable & Shadow>): Chainable<S>
          get<E extends Node = HTMLElement>(selector: string, options?: Partial<Loggable & Timeoutable & Withinable & Shadow>): Chainable<JQuery<E>>
        }
      }
    }
    

    Now cy.get('@alias') types to any (because of get<S = any>), which is valid since aliases store any type.

    But also the selector version is getting typed to any as well, it seems the identical type signatures make one of the defns redundant.

    As Mikhail Bolotov points out, a different command name solves the issue, but I would define it as a custom command in /cypress/support/index.ts and call it getAlias since it has to work for any type.