3

I'm building an app with Cypress and TypeScript.

I have the following code, which slightly alters the behaviour of the Magic SDK based on whether it runs inside of an E2E tests, or not:

const magic = new Magic(window.ENV.MAGIC_PUBLISHABLE_KEY, {
  testMode: Boolean(window.Cypress),
});

TypeScript complains about window.Cypress and says:

Property 'Cypress' does not exist on type 'Window & typeof globalThis'.

How can I tell TypeScript about Cypress? Basically I need something like this:

type Window = {
  Cypress?: Cypress; // Where Cypress is the Cypress namespace
}

I found this answer (amongst others) in Google but I couldn't see how that would solve this specific issue.

EDIT:

The question Tobias linked in a comment is different because if you do:

declare global {
  Cypress: Cypress;
}

TypeScript complains that:

Unexpected labeled statement.

And when you do:

declare global {
  var Cypress: Cypress;
}

TypeScript complains that:

Cannot augment module 'Cypress' with value exports because it resolves to a non-module entity.

I couldn't find the code on Github, but in my node_modules it lives here:

enter image description here

So the solutions from the suggested answer won't work, because Cypress is a namespace, and not a type - though to solve this question you probably need it to be a type.

EDIT 2:

Fody's answer doesn't work, either.

enter image description here

J. Hesters
  • 13,117
  • 31
  • 133
  • 249
  • 1
    Does this answer your question? [How do you explicitly set a new property on \`window\` in TypeScript?](https://stackoverflow.com/questions/12709074/how-do-you-explicitly-set-a-new-property-on-window-in-typescript) – Tobias S. May 06 '22 at 18:23
  • If the above question/answer doesn't help, could you include why it doesn't or any trouble you have implementing the solutions? – kelsny May 06 '22 at 20:37
  • @catgirlkelly I just did! :) Thanks for any help. – J. Hesters May 06 '22 at 20:41

3 Answers3

4

After some playing around the following seems to work:

declare global {
  interface Window {
    Cypress?: Cypress.Cypress;
  }
}

if (window.Cypress) {
  // ...
}
J. Hesters
  • 13,117
  • 31
  • 133
  • 249
1

The pattern used by Gleb Bahmutov in his slides is

interface Window {
  Cypress? : any    // don't really need strict type here
}

if (window.Cypress) {   
  ...
}
Fody
  • 23,754
  • 3
  • 20
  • 37
  • Thanks for you help! Typesafety would be awesome, I mean why use TypeScript otherwise? But anyways, this doesn't work. Will attach screenshot in the question :) – J. Hesters May 06 '22 at 20:49
  • I don't get that - looks like it's related to the error above on `Window`. What is that error? – Fody May 06 '22 at 20:55
0

Assign the namespace to a declared constant and export it:

declare global {
  export declare const Cypress: Cypress;
}

Not 100% sure if this works, things with ambient type declarations are always a bit finnicky.

kelsny
  • 23,009
  • 3
  • 19
  • 48
  • Thanks for the help! Unfortunately, this gives three errors: `A 'declare' modifier cannot be used in an already ambient context.`, `Cannot augment module 'Cypress' with value exports because it resolves to a non-module entity.` and `Cannot use namespace 'Cypress' as a type.`. – J. Hesters May 06 '22 at 20:48
  • 1
    Oh it's a namespace... Totally missed that. – kelsny May 06 '22 at 20:50