Search code examples
typescriptwdio-v6

type ‘(v1: number, callback: Function) => Promise<void>' is not assignable to parameter of type 'string | ((arguments_0: number) => void)'


After updating from wdio v5 to wdio v6 (6.11.0 with "typescript": "^4.2.2"), I started getting the below error on browser.executeAsync(runCheck, v1)

error TS2345: Argument of type ‘(v1: number, callback: Function) => Promise<void>' 
is not assignable to parameter of type 'string | ((arguments_0: number) => void)'.

Below is my code:

const runCheck = async (
  v1: number,
  callback: Function
): Promise<void> => {
...
...
...
  callback(v1);
};


const canReceive = (
  browser: WebdriverIO.BrowserObject,
): boolean => {
  const v1 = 50;
   const rate = browser.call(() =>
      browser.executeAsync(runCheck, v1)
    );
  return rate > 10; 
};


I have tried modifying

Promise<void> to Promise<any>

but doesn't seem to help. Any points on how to fix the issue is appreciated.

Thank you in advance.


Solution

  • TLDR, I think the typescript type definitions are wrong in wdio 6.

    Try typing runCheck as any to workaround the problem.

    import { expect } from 'chai';
    import { Browser } from 'webdriverio'
    
    describe('WebdriverIO 6', () => {
        it("has broken typescript type definitions", () => {
            const runCheck: any = 
                async (v1: number, callback: Function): Promise<void> => {
                    callback(v1);
                };
    
    
            const canReceive = 
                async (browser: WebdriverIO.BrowserObject): Promise<boolean> => {
                    const v1 = 50;
                    const rate = await browser.call(() => browser.executeAsync(runCheck, v1));
                    return rate > 10; 
                };
        })
    })
    

    Long version.

    I took a look at the docs for browser.executeAsync, it looks like you're passing arguments which it should accept.

    "The script argument defines the script to execute in the form of a function body. The function will be invoked with the provided args array and the values may be accessed via the arguments object in the order specified. The final argument will always be a callback function that must be invoked to signal that the script has finished." https://v6.webdriver.io/docs/api/browser/executeAsync.html

    On checking the type definitions for executeAsync, I saw this

            // there is no way to add callback as last parameter after `...args`.
            // https://github.com/Microsoft/TypeScript/issues/1360
            // executeAsync: <T>(script: string | ((...arguments: any[], callback: (result: T) => void) => void), ...arguments: any[]) => Promise<T>;
            /**
             * Inject a snippet of JavaScript into the page for execution in the context of the currently selected frame.
             * The executed script is assumed to be asynchronous and must signal that is done by invoking
             * the provided callback, which is always provided as the final argument to the function. The value
             * to this callback will be returned to the client.
             */
            executeAsync: <U extends any[], V extends U>(script: string | ((...arguments: V) => void), ...arguments: U) => Promise<any>;