I was reading this article about Cypress. On the last part, the author overrode the types to be inferred by typescript when calling Cypress.env
.
Here's the snippet that i want to understand.
export { };
declare global {
namespace Cypress {
export interface Cypress {
/**
* Returns all environment variables set with CYPRESS_ prefix or in "env" object in "cypress.json"
*
* @see https://on.cypress.io/env
*/
env(): Partial<EnvKeys>;
/**
* Returns specific environment variable or undefined
* @see https://on.cypress.io/env
* @example
* // cypress.json
* { "env": { "foo": "bar" } }
* Cypress.env("foo") // => bar
*/
env<T extends keyof EnvKeys>(key: T): EnvKeys[T];
/**
* Set value for a variable.
* Any value you change will be permanently changed for the remainder of your tests.
* @see https://on.cypress.io/env
* @example
* Cypress.env("host", "http://server.dev.local")
*/
env<T extends keyof EnvKeys>(key: T, value: EnvKeys[T]): void;
/**
* Set values for multiple variables at once. Values are merged with existing values.
* @see https://on.cypress.io/env
* @example
* Cypress.env({ host: "http://server.dev.local", foo: "foo" })
*/
env(object: Partial<EnvKeys>): void;
}
}
}
interface EnvKeys {
'boards': Array<{
created: string;
id: number;
name: string;
starred: boolean;
user: number;
}>;
'lists': Array<{
boardId: number
title: string
id: number
created: string
}>;
}
Few questions that I have in this snippet:
- How does typescript know about this file when it is named as
env.d.ts
? I know that typescript automatically know the types if the file is named the same with the file (e.gcommand.ts
->command.d.ts
- What's the use of
export {}
here. If i comment this one out, Vscode complains. - Why do we have to add
declare global
here when the original Cypress typescript starts withdeclare namespace Cypress
?
I'm not an expert in typescript, but here's my take
1. How does typescript know about this file when it is named as env.d.ts
In
tsconfig.json
you havewhich means
env.d.ts
is included in the compile.Run
tsc --listFiles --noEmit
to see what get's included.2. What's the use of export {} here
You are merging namespaces, and the docs Merging Namespaces say
Further
So, it's information hiding - like public vs private variables.
Oops wrong anwser
I just realized you want to know about the first line.
Please see this answer
Augmentations for the global scope can only be directly nested in external modules or ambient module declarations(2669)
3. Why do we have to add declare global
Ref Global augmentation
When you write a test, you can use
Cypress.Commands.add()
,cy.get()
,it()
, etc without needing to import anything because they are declared globally.To merge with the global Cypress interface, your enhancement must also be declared as global.
To see the effect, change
env.d.ts
and
addTaskApi.ts