Using Cypress.Promise in a Cypress command causes type conflicts

When using Cypress 8.x.x, the following Cypress command works fine:

declare global {
  namespace Cypress {
    interface Chainable<Subject> {
      login(): Chainable<Token>;
    }
  }
}
Cypress.Commands.add('login', () => {
  return new Cypress.Promise((resolve, reject) => {
    // rest
  });
});

However, upon updating to Cypress 9.x.x, I encounter this TypeScript error:

argument of type '() => Bluebird<unknown>' is not assignable to parameter of type '(person?: Partial<Person>) => Chainable<Token>'.
  Type 'Bluebird<unknown>' is missing the following properties from type 'Chainable<Token>': and, as, blur, check, and 83 more.ts(2345)

Answer №1

The issue lies in the discrepancy between the implementation and the expected typing: the actual return value (new Cypress.Promise(…)) is a promise, or more specifically a PromiseLike, rather than a Token1.

Given that Cypress utilizes Bluebird promises, to align with the implementation, the return type of login() should also be a Bluebird promise; you can achieve this by importing the symbol from the Cypress package as follows:

import type Bluebird from "cypress/types/bluebird";

declare global {
    namespace Cypress {
        interface Chainable {
            login(): Bluebird<Token>;
        }
    }
}

Give it a try2.

1 – Just an FYI, the OP doesn't specify what Token represents, so technically it could be a PromiseLike. However, I find this scenario to be unlikely. Unfortunately, user @PeaceAndQuiet's related question was left unanswered, leading me to assume that Token isn't a PromiseLike (probably an access token).

2 – Keep in mind that cypress may not be recognized by the playground for some reason; even though it is npm-installed (navigate to Plugins → scroll down)

Answer №2

Version 9.0.0 introduced some significant changes that you should be aware of. For more details, check out the changelog for version 9.0.0. One particular change to pay attention to is the 6th one listed in the changelog, which relates to feature 17496.

To avoid any issues, make sure to replace <Token> with something that supports Bluebird promises. Alternatively, you can set it to <any>.

declare global {
  namespace Cypress {
    interface Chainable<Subject> {
      login(): Chainable<any>;
    }
  }
}

Answer №3

The issue with TypeScript was caused by a major change in version 9.0.0. To learn more about this update, visit the changelog:

One significant change is that custom command implementations are now typed according to the declared custom chainables. This addresses #17496.

This means that the return value in your implementation must align with the declared typings/custom chainables.

In your scenario, you are returning a Bluebird promise:

return new Cypress.Promise((resolve, reject) => { ... });

To resolve this, you need to update your typing interface to match the type. This can be achieved through:

declare global {
  namespace Cypress {
    interface Chainable {
      login(): Cypress.Promise<Token>;
    }
  }
}

Alternatively, following @Dima Parzhitsky's recommendation, you can do the following:

import type Bluebird from 'cypress/types/bluebird';

declare global {
  namespace Cypress {
    interface Chainable {
      login(): Bluebird<Token>;
    }
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating an NPM package that utilizes global types without altering the project it is integrated with

The Dilemma: When working on a project that involves reusing multiple types across various files, utilizing types defined in a script file can be advantageous. These global types are accessible throughout the entire project without the need for importing, ...

Identifying the specific type within a union of types using a discriminator

How can I specify the correct typing for the action argument in the function withoutSwitchReducer as shown below? enum ActionTypesEnum { FOO = 'FOO', BAR = 'BAR', } type ActionTypes = { type: ActionTypesEnum.FOO, paylo ...

IntersectionObserver activates prior to element's entrance into the viewport

I've set up a Vue component with the following structure: <template> <article> <!-- This content spans several viewport heights: you *have* to scroll to get to the bottom --> {{ content }} </article> <span ref ...

Guidelines for simulating ActivatedRouteSnapshot in observable testing situations

I am currently testing an observable feature from a service in Angular. This particular observable will output a boolean value based on the queryParam provided. For effective testing of this observable, it is essential to mock the queryParam value. Howev ...

Learn the art of generating multiple dynamic functions with return values and executing them concurrently

I am currently working on a project where I need to dynamically create multiple functions and run them in parallel. My starting point is an array that contains several strings, each of which will be used as input for the functions. The number of functions ...

What is the process for deploying a Lambda function using Terraform that has been generated with CDKTF

Currently, I am following a tutorial by hashicorp found at this link. The guide suggests using s3 for lambda deployment packages. // in the process of creating Lambda executable const asset = new TerraformAsset(this, "lambda-asset", { ...

The feature of declaration merging does not function properly with the express 4.17.* request type

Looking to enhance the Request type, I decided to create a folder @types/express. Within this folder, I included a file index.d.ts with the following content. namespace Express { interface Request { user: number; } } Upon referencing req.user in V ...

Combining and Filtering Arrays of Objects with Angular

I possess: arrayBefore arrayBefore = [{name:'n1', items: [i1]}, {name:'n2', items: [i2]}, {name:'n1', items: [i3]}] I desire to craft a function: myFunction myFunction(arrayBefore) In order for it to generate: arrayAfte ...

Set certain properties within the nested object to be optional

Within a TypeScript project, there exists a type definition that looks like this: type Bar = { x: string; y: string; data: { z: string; w: string; }; }; This type is imported and widely used throughout the project, making it impossible for ...

Validity of Vue 3 Typescript properties checked during compilation and runtime

We are currently developing a Vue 3 component library, and as the project grows in scale, we have refactored it with TypeScript to improve the development experience. However, we are facing a challenge. Our library is being used by teams in different envir ...

Adjust the tally of search results and modify the selection depending on the frequency of the user's searches within an array of objects

Seeking assistance with adding a new function that allows users to navigate to the next searched result. Big thanks to @ggorlen for aiding in the recursive search. https://i.stack.imgur.com/OsZOh.png I have a recursive search method that marks the first ...

How can I apply unique "compilerOptions" settings to a specific file in tsconfig.json file?

Can I apply specific tsconfig options to just one file? Here is my current tsconfig.json: { ... "compilerOptions": { ... "keyofStringsOnly": false, "resolveJsonModule": true, "esModuleInterop": t ...

The ultimate guide to loading multiple YAML files simultaneously in JavaScript

A Ruby script was created to split a large YAML file named travel.yaml, which includes a list of country keys and information, into individual files for each country. data = YAML.load(File.read('./src/constants/travel.yaml')) data.fetch('co ...

Having trouble halting the execution at specific checkpoints within an asp.net core project containing an angular 8.0 application located in a subfolder named ClientApp

Encountering difficulties stopping at breakpoints in an asp.net core project with an angular 8.0 app located in a subfolder within ClientApp. The app I need to set a breakpoint in is located at clientapp\apps\microsympan\app\src\ap ...

Switch up row values in an array and transform them into an object using SheetJS

I am struggling to format an array where each "Working Day" is represented as an object with specific details like index and start/end date. I need help manipulating the JSON data to achieve the desired structure. The package I'm currently using is: ...

Updates made in the type declaration files are not being displayed

I'm currently working on an express app and I have been trying to add a new property to the Request's class instance. To achieve this, I created a type.d.ts file at the root of my project that looks like this: type User = { name: string } de ...

Guide on extracting just the key and its value from a Filter expression in a DynamoDB Query using Typescript

Presented here is a filter expression and Key Condition. The specific set of conditions are as follows: {"Age":{"eq":3},"Sex":{"eq":"MALE"}} const params: QueryCommandInput = { TableName: my_tab ...

Issue with the recursive function in javascript for object modification

I have all the text content for my app stored in a .json file for easy translation. I am trying to create a function that will retrieve the relevant text based on the selected language. Although I believe this should be a simple task, I seem to be struggl ...

Methods for defining a variable in React with Typescript without encountering the "Index signature is missing in type" issue

I am facing an issue while trying to declare a variable 'reports' and assigning it to an array of arrays containing string and number types. The problem arises when I try to assign it, resulting in errors. ... // Retrieving data from an API let ...

The onChange event does not work as expected for Select controls

I am facing an issue with my common useForm.tsx file when handling the onChange event for select controls. The error message I encounter is displayed below. Does anyone have any suggestions on how to resolve this? Error: Type '(e: ChangeEvent<HTM ...