cypress: Adding custom commands with typescript definitions leads to error
Cypress.Commands.add('myCustomCommand', '...')
Using TypeScript now results in…
Property ‘myCustomCommand’ does not exist on type ‘Chainable’)
How do we fix this @NicholasBoll @bahmutov
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 33
- Comments: 47 (24 by maintainers)
Commits related to this issue
- lots of refactors for cypress tests still not passing troubleshooting from https://github.com/cypress-io/cypress/issues/1065 — committed to Atticus29/dataJitsu by Atticus29 5 years ago
I was looking at the examples
preprocessors__typescript-webpackandpreprocessors__typescript-browserify. TypeScript will not allow you to extend a namespace if the file is amodule(has import/export/require). To get around this in the example, thecommand.tsfile(s) cannot import/export anything. They simple contain the following code:commands.ts:Some other file:
And the index.ts simply imports it:
import './command'. I’ll also note thetsconfig.jsonneeds to include all files in support for this to work (it looks like it does).@shcallaway is exactly right. Chainable interfaces have to be extended:
Later:
I fixed it by adding
index.d.tsfile in mycommandsfolder. In this file I added something like this:If You don’t import or export anything, just omit global namespace declaration:
Keep in mind that it won’t work with Typesciprt < 2.3, becuase default generics type has to be supported.
I had issues declaring the namespace when importing other files into
commands.ts. I ran across this solution which worked for me:https://github.com/cypress-io/add-cypress-custom-command-in-typescript/issues/2#issuecomment-389870033
Just wanted to help anyone else find that if they end up on this thread.
Any update with the version 2.x of cypress ? I have the same issue:
I am using cypress 2.1.0 and ts 2.7.1
Is https://github.com/bahmutov/add-typescript-to-cypress still necessary ? Ts seems to work without webpack preprocessor …
For future readers, this is the TypeScript concept that makes it possible to re-declare the Cypress namespace: declaration merging.
Also, @NicholasBoll , regarding your example, what is the purpose of adding the generic?
Also I strongly encourage people use regular functions instead of custom commands: https://medium.com/@NicholasBoll/cypress-io-scaling-e2e-testing-with-custom-commands-6b72b902aab
A few days ago, I made the migration of e2e javascript tests from cypress to typescript.
All is not completely finished because the return type on each command is any. To do so, I just have to import the desired return types for each order.
command.d.ts :
Note that at the very beginning of the file
, I added this magic line:
which allows me to recognize the type definitions for node and thus, to have a typescript file.
Here are the changes to supportFile and pluginsFile to do :
Here are the versions of the dependencies I use :
If it interests people, I share a link to the cypress directory of my project :
https://gitlab.com/linagora/petals-cockpit/tree/master/frontend/cypress
Hmm I’m still getting errors (e.g.
Property 'goToPage' does not exist on type 'Chainable'.). I don’t think declaration merging is working — possibly because of these two lines incypress/index.d.ts?Here is my
cypress/support/commands.ts:Here is my
cypress/tsconfig.cypress.json:And I don’t think it matters, but here is my
cypress/plugins/index.js:Dunno if this is solved but I ran in the same problem… Following official guides doesn’t allow me pretty much for importing any custom types to cover for custom commands definition types. However this seem to kind of work.
// cypress/support/commands.ts// cypress/support/types.d.tsI was having this problem. TS and custom Cypress commands were working fine, but I after I added another custom command, everything broke.
I think it was b/c I was importing something into my
cypress.d.tsin the wrong spot.@shcallaway, I just checkout out the branch that @bahmutov provided: https://github.com/cypress-io/snapshot/pull/11/files and changed a few things to verify:
That is working for me.
getBodyis known and can be chained.then change to
you saved my life before i have used like these and i am worries if i have a lot of data
so i use your code
thankyou 🚀
This worked, but the index and command files have to be .js files - i wrongly still had them as .ts , which gives compilation errors.
I got that same error when I used an
importincommands.ts. I had to not have any import/export in that file (makes TypeScript treat as a module). Not sure why TS thinks they are unrelated in that case.The
tsconfigwas a little tricky, but I think I’m doing it the same as you. Mytsconfig.jsonlooks like this:./cypress/tsconfig.jsonNote the
baseUrland theincludewith../node_modules.Also make sure you don’t have
@types/cypresslurking in your node_modules. I was getting duplicate and conflicting definitions. Those types are pre-1.0.@shcallaway Note the snapshot repo is using Cypress 1.1.4 which has no generic. 1.2.0 adds the
Subjectgeneric. This shouldn’t effect any implementation, but if you are creating your own commands in TypeScript the interface declaration will change slightly:@shcallaway I added the Generic (should be available on Cypress 1.2.0, but not on Cypress 1.1.4) to allow they subject to be passed around so that the
.thentype would be known. For backwards compatibility, the Subject is defaulted toany. For example:Without the generic, the subject would always be
anyYes, I suppose that is all you need. That should work fine. Unless the custom command returns things other than more cypress commands, it can return void.
I’ll just note there are some subtleties to TypeScript modules. TypeScript defines global declarations as a
namespaceand anything with an require/import/export as amodule. Amodulehas it’s own local scope. Anamespaceparticipates in a global scope. Since Cypress has no exports, it is anamespace.You can actually mix them for
UMDmodules.Example:
Chai exports a namespace because their API is chainable and you’ll need access to that namespace in order to extend the
Assertioninterface. But they also export a const calledchai: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/chai/index.d.ts#L1616More info about TypeScript modules can be found here: https://www.typescriptlang.org/docs/handbook/modules.html