Home > OS >  Type '{id: number; ...}' is not assignable to type void | Chainable<any>
Type '{id: number; ...}' is not assignable to type void | Chainable<any>

Time:01-06

We just recently started migrating from JS to typescript in our Cypress project.

I have a custom command:

export {}

declare global {
    namespace Cypress {
        interface Chainable {
            getInfo(body: object): Chainable<any>
        }
    }
}

Cypress.Commands.add('getInfo', (body: object) => {
    let info: {
        id: number;
        firstName: string;
        lastName: string
    } = {
        id: 0,
        firstName: '',
        lastName: ''
    }

    cy.request({
        method: 'POST',
        url: '/api/order',
        body: body
    }).then(response => {
            info.id = response.body.customer.id
            info.firstName = response.body.customer.firstName
            info.lastName = response.body.customer.lastName
        })

    return info
})

Unfortunately I get an underline error on the (body: object) => { portion

Error is as follows:

Argument of type '(body: object) => { id: number; firstName: string; lastName: string; }' is not assignable to parameter of type 'CommandFn<\"getInfo\">'.\n  Type '{ id: number; firstName: string; lastName: string; }' is not assignable to type 'void | Chainable<any>'

What am I possibly doing wrong here?

CodePudding user response:

Lowercase 'o' object is a primitive in JS/TS, and doesn't behave the way that you are trying to use it. A quick fix would probably be to type body as Uppercase 'O' Object.

Additionally, if body is going to be of the same type as the info variable, you could make a custom type.

interface Info {
  id: number;
  firstName: string;
  lastName: string;
}

Cypress.Commands.add('getInfo', (body: Info) => {
  const info: Info = {
    id: 0,
    firstName: '',
    lastName: ''
  };

  cy.request({
    method: 'POST',
    url: '/api/order',
    body
  }).then((response) => {
    info.id = response.body.customer.id;
    info.firstName = response.body.customer.firstName;
    info.lastName = response.body.customer.lastName;
  });

  return info;
});

When in doubt, always try to type your variables as much as possible, and then start working backwards to get to the "simplest" implementation.

CodePudding user response:

From the typescript POV you should be able to return cy.wrap(info) to make the return type as Chainable<any>.

But another problem is delay in cy.request({...}) resolving probably means the value returned is the empty info object.

Try this instead

export {}

declare global {
    namespace Cypress {
        interface Chainable {
            getInfo(body: object): Chainable<any>
        }
    }
}

Cypress.Commands.add('getInfo', (body: object) => {

    // return the request here so that the response is awaited

    return cy.request({
        method: 'POST',
        url: '/api/order',
        body: body
    }).then(response => {

        let info: {
          id: number;
          firstName: string;
          lastName: string
        } = {
          id: response.body.customer.id,
          firstName: response.body.customer.firstName,
          lastName: response.body.customer.lastName
        }

        // return the info here so that the response is modified 
        return info  
    })
})
  • Related