'How can I force TypeScript to check a cy.task argument's type?

If I specify type of a Cypress task as follows:

// X and Y are some types
function a(arg: X): Y { ... }

...
on('task', { a })

declare global {
  namespace Cypress {
    interface Chainable {
      task(event: 'a', arg: X): Chainable<Y>;
    }
  }
}

I've found that TypeScript unfortunately happily accepts

cy.task('a', notAnX)

because it falls back to the default definition from cypress.d.ts

task<S = unknown>(event: string, arg?: any, options?: Partial<Loggable & Timeoutable>): Chainable<S>

Can I change my declaration in some way to make this an error?

EDIT: There is a similar request in https://github.com/Microsoft/TypeScript/issues/19064, but nobody suggests any currently working solutions, so my guess is that it's impossible for now (except for copying cypress.d.ts and removing that overload).



Solution 1:[1]

As a workaround, it should be possible to do the following if you use TypeScript ESLint with type information:

  1. Declare interface TypeError {}
  2. Add a new task overload together with the actual tasks:
    task(event: string, arg?: any, options?: Partial<Loggable & Timeoutable>): TypeError
    
  3. Add a custom rule to ESLint to disallow any uses of TypeError.

My initial attempt was to use never but some cases I would prefer not to type-check still type-checked.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alexey Romanov