4

I'm using cypress and declaring namespace to infer type of custom commands.

index.d.ts

declare namespace Cypress {
  interface Chainable {
    commandA: typeof commandA;
  }
}

commands.ts

const commandA = ...;

Cypress.commands.add('commandA', commandA);

In this context, I have to use CyHttpMessages type in cypress/types/net-stubbing package. So I imported that type in commands.ts file.

commands.ts (with import)

import { CyHttpMessages } from 'cypress/types/net-stubbing';

...

But, after importing that type index.d.ts file was broken with red lines. This file couldn't find type of commandA function. I think import statement is cause of this problem.

How can I use import statement with declare namespace ? What is the problem? Thanks for your reading.

undefined
  • 978
  • 1
  • 12
  • 30
  • I have this same issue Make any progress in figuring it out? – Ruben Martinez Jr. Jan 19 '22 at 19:39
  • Hi, could you please spin up a minimal reproducible example for me? I once had an issue similar to yours with [playwright](https://playwright.dev/) fixtures and I solved it through some wierdo magic. The project config was very specific though so I not sure if it would apply here without further context :). – Filip Kaštovský Jan 20 '22 at 15:30

2 Answers2

1

You need to use the declare global {} when setting up the Typescript definition for custom Cypress commands.

The documentation provides an example but based on the provided information it should look like this:

index.d.ts

/// <reference types="cypress" />

declare global {
  namespace Cypress {
    interface Chainable {
      commandA(): Chainable<Element>
    }
  }
}
Noah
  • 859
  • 7
  • 17
0

A solution with namespaces (not recommended) To resolve your issue, you can export your namespace:

// UtilBase.ts
import * as path from "path";
export namespace My.utils {
    export class UtilBase {
        protected fixPath(value: string): string {
            return value.replace('/', path.sep);
        }
   }
}

Then, you should be able to import it:

// UtilOne.ts
import {My} from './UtilBase';
namespace My.utils {
    export class UtilOne extends My.utils.UtilBase {
    }
}

However, if the purpose is to organize the code, it is a bad practice to use namespaces and (ES6) modules at the same time. With Node.js, your files are modules, then you should avoid namespaces.

Use ES6 modules without namespaces TypeScript supports the syntax of ES6 modules very well:

// UtilBase.ts
import * as path from "path";
export default class UtilBase {
    protected fixPath(value: string): string {
        return value.replace('/', path.sep);
    }
}

// UtilOne.ts
import UtilBase from './UtilBase';
export default class UtilOne extends UtilBase {
}

It is the recommended way. ES6 modules prevent naming conflicts with the ability to rename each imported resource.

Use a file tsconfig.json instead of /// <reference

// tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es6"
  },
  "exclude": [
    "node_modules"
  ]
}

This is from a different answer, here.