then() returns correct type when undefined is used. (#7997)

This commit is contained in:
Kukhyeon Heo
2020-07-16 22:48:20 +09:00
committed by GitHub
parent c2dc7572b6
commit 4dd30a6003
2 changed files with 35 additions and 0 deletions

View File

@@ -492,6 +492,10 @@ declare namespace Cypress {
}
type CanReturnChainable = void | Chainable
type ThenReturn<S, R> =
R extends void ? Chainable<S> :
R extends R | undefined ? Chainable<S | Exclude<R, undefined>> :
Chainable<S>
/**
* Chainable interface for non-array Subjects
@@ -1751,12 +1755,24 @@ declare namespace Cypress {
* @see https://on.cypress.io/then
*/
then<S extends object | any[] | string | number | boolean>(fn: (this: ObjectLike, currentSubject: Subject) => S): Chainable<S>
/**
* Enables you to work with the subject yielded from the previous command / promise.
*
* @see https://on.cypress.io/then
*/
then<S>(fn: (this: ObjectLike, currentSubject: Subject) => S): ThenReturn<Subject, S>
/**
* Enables you to work with the subject yielded from the previous command / promise.
*
* @see https://on.cypress.io/then
*/
then<S extends object | any[] | string | number | boolean>(options: Partial<Timeoutable>, fn: (this: ObjectLike, currentSubject: Subject) => S): Chainable<S>
/**
* Enables you to work with the subject yielded from the previous command / promise.
*
* @see https://on.cypress.io/then
*/
then<S>(options: Partial<Timeoutable>, fn: (this: ObjectLike, currentSubject: Subject) => S): ThenReturn<Subject, S>
/**
* Enables you to work with the subject yielded from the previous command.
*

View File

@@ -179,6 +179,25 @@ cy.wrap(['bar', 'baz'])
})
describe('then', () => {
// https://github.com/cypress-io/cypress/issues/5575
it('should respect the return type of callback', () => {
// Expected type is verbose here because the function below matches 2 declarations.
// * then<S extends object | any[] | string | number | boolean>(fn: (this: ObjectLike, currentSubject: Subject) => S): Chainable<S>
// * then<S>(fn: (this: ObjectLike, currentSubject: Subject) => S): ThenReturn<Subject, S>
// For our purpose, it doesn't matter.
const result = cy.get('foo').then(el => el.attr('foo'))
result // $ExpectType Chainable<JQuery<HTMLElement>> | Chainable<string | JQuery<HTMLElement>>
const result2 = cy.get('foo').then(el => `${el}`)
result2 // $ExpectType Chainable<string>
const result3 = cy.get('foo').then({ timeout: 1234 }, el => el.attr('foo'))
result3 // $ExpectType Chainable<JQuery<HTMLElement>> | Chainable<string | JQuery<HTMLElement>>
const result4 = cy.get('foo').then({ timeout: 1234 }, el => `${el}`)
result4 // $ExpectType Chainable<string>
})
it('should have the correct type signature', () => {
cy.wrap({ foo: 'bar' })
.then(s => {