使用声明文件覆盖赛普拉斯打字稿

Overriding Cypress typescript using declaration file

我正在阅读这篇关于 Cypress 的 article。在最后一部分,作者在调用 Cypress.env.

时覆盖了 typescript 推断的类型

这是我想了解的片段。

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
  }>;
}

我在这段代码中有几个问题:

  1. typescript 如何知道这个名为 env.d.ts 的文件?我知道如果文件与文件同名,则打字稿会自动知道类型(例如 command.ts -> command.d.ts
  2. 这里export {}有什么用。如果我评论这个,Vscode 抱怨。
  3. 为什么我们必须在这里添加 declare global,而原始的 Cypress 打字稿以 declare namespace Cypress 开头?

我不是打字专家,但这是我的看法

1.当它被命名为 env.d.ts

时,打字稿如何知道这个文件

tsconfig.json你有

include": [
  "**/*.ts"
]

这意味着 env.d.ts 包含在编译中。

运行 tsc --listFiles --noEmit 查看包含的内容。


2。这里的export {}有什么用

您正在合并命名空间,文档 Merging Namespaces

To merge the namespaces, type definitions from exported interfaces declared in each namespace are themselves merged.

进一步

Non-exported members are only visible in the original (un-merged) namespace. This means that after merging, merged members that came from other declarations cannot see non-exported members.

所以,它是信息隐藏 - 就像 public vs 私有变量。

糟糕,回答错误

我刚意识到你想知道第一行。

请看这个回答

I think the trick is just that an "external module" is a file containing an import or export statement, so this makes it an "external module".


3。为什么我们要加上 declare global

参考 Global augmentation

You can also add declarations to the global scope from inside a module

编写测试时,您可以使用 Cypress.Commands.add()cy.get()it() 等,无需导入任何内容,因为它们是全局声明的。

要与全局赛普拉斯界面合并,您的增强功能也必须声明为全局。

要看效果,改env.d.ts

declare module "env" {  
  namespace Cypress {

addTaskApi.ts

Cypress.Commands.add('addTaskApi', ({ title, boardIndex = 0, listIndex = 0 }) => {
  cy.request('POST', '/api/tasks', {
      title,
      boardId: Cypress.env('boards')[boardIndex].id,
      listId: Cypress.env('lists')[listIndex].id
    })
    .then(({ body }) => {

      const tasks = Cypress.env('tasks')  // tasks typed as any 
                                          // instead of  'tasks': Array<{ boardId:...number;
      tasks.push(body);
    })
})