I spent a good part of today grappling with this issue, but I finally figured it out.
If you are working with @types/webdriverio, the key is to extend the WebdriverIO.Client interface with your custom command declaration. It's best practice to define your custom command in a .ts file. Here's an example of how to do it:
declare global {
namespace WebdriverIO {
interface Client<T> {
doCustomThing: typeof doCustomThing;
}
}
}
function doCustomThing() {
console.log("test");
}
//now you can use both of these
browser.addCommand('doCustomThing' , doCustomThing)
browser.doCustomThing();
If incorporating custom commands into typescript proves challenging, you can declare them separately in a .d.ts file like so:
declare namespace WebdriverIO {
interface Client<T> {
doCustomThing(): void;
}
}
However, by going this route, you'll need to manage separate declaration and implementation files, ensuring they remain aligned. This approach should be reserved for cases where keeping the implementation in plain JS is unavoidable.
These steps were verified using Typescript 2.6.1, webdriverio 4.9.10, and @types/webdriverio 4.8.6.
Note: In the first set of instructions, explicit mention is made that you are altering the definition of the WebdriverIO namespace in the global context. Conversely, in the second set, you're implicitly operating within the global scope. The distinction arises from the first being enclosed in a module, while the second isn't categorized as such due to its lack of import or export statements. For more details, refer to https://www.typescriptlang.org/docs/handbook/modules.html.