WebStorm highlights user-defined Jasmine matchers as mistakes and displays `TypeScript error TS2339: Property 'matcher' does not exist on type 'ArrayLikeMatchers '`

I am currently working on testing a hybrid Angular and Angular.js app using Karma / Jasmine. The previous code utilized custom matchers which worked flawlessly, and these same matchers are being used in the new TypeScript code. Strangely, although the TypeScript compiler for Webpack compiles and runs the spec's without any issues, the WebStorm inspector is flagging them as errors with the message:

https://i.sstatic.net/mEoEH.png

The specific error reads:

TS2339: Property 'toBeNgVisible' does not exist on type 'ArrayLikeMatchers '.

The environment setup includes:

  • "@types/angular-mocks": "^1.5.11",
  • "@types/jasmine": "^3.3.1",
  • "@types/jasmine-jquery": "^1.5.33",
  • "@types/jquery": "^1.10.33",
  • "@angular/upgrade": "^9.1.13",
  • "@angular/core": "^9.1.13",
  • "angular": "^1.8.2",
  • "angular-mocks": "^1.8.2",
  • "typescript": "^3.8.3",
  • "karma": "^5.2.3",
  • "karma-jasmine": "^3.3.1",
  • "karma-webpack": "^4.0.2",
  • "jasmine-core": "^3.5.0",

The custom matchers have been defined in JavaScript like so:

const matchers = {
  toBeNgVisible: () => {
    return {
      compare: function (actual) {
        return {
          pass: actual && $(actual).closest('[hidden]').length === 0;,
          message: 'Expected "' + actual + '," and all of its parents, to not have a hidden attribute.'
        };
      }
    };
  }
}
beforeEach(() => { jasmine.addMatchers(matchers); });

I also have a declaration file named matchers.d.ts, which looks like:

declare namespace jasmine {
  interface Matchers<T> {
    toBeNgVisible(): boolean;
  }
}

My tsconfig file does not contain any file includes/excludes, and the matchers.d.ts file is included in the files list.

This issue is causing confusion and hindering efficient development. If anyone has encountered this problem before, or has any advice on what I can try next, I would greatly appreciate it. I'm unsure whether the issue lies within my Webpack configuration or my WebStorm configuration, so any suggestions are welcome.

Answer №1

I have encountered this issue before.

My Suggestion

You can avoid the need for a separate declaration file by decorating the global Jasmine namespace instead. The following syntax should work fine, and the WebStorm inspector should approve:

In matchers.ts:

declare global {
  namespace jasmine {
    interface Matchers<T> {
      toBeNgVisible<V>(): boolean;
    }
  }
}

export const Matchers: jasmine.CustomMatcherFactories = {
  toBeNgVisible: () => {
    // ... your implementation here
  }
}

You still have to add the matchers to Jasmine before running tests, but this method has been effective in my case.

You can refer to this approach here (last comment).

Original Advice

To get around this issue, you can simply rename the declaration file so it doesn't share the same name. For instance:

matchers.ts
matchers.d.ts       <-- won't work if named like this
matcher-types.d.ts  <-- renaming resolves the problem with WebStorm

I'll try to locate the source that guided me to this solution, but feel free to give it a try in the meantime.

-edit- The answer can actually be found in an existing post at

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I am hoping to refresh my data every three seconds without relying on the react-apollo refetch function

I am currently working with React Apollo. I have a progress bar component and I need to update the user's percent value every 3 seconds without relying on Apollo's refetch method. import {useInterval} from 'beautiful-react-hooks'; cons ...

Display the ion-button if the *ngIf condition is not present

I am working with an array of cards that contain download buttons. My goal is to hide the download button in the first div if I have already downloaded and stored the data in the database, and then display the second div. <ion-card *ngFor="let data o ...

NestJS RabbitMQ Microservice Integration

Currently, I am attempting to establish a connection to a Rabbit MQ docker container through NestJS microservice. The setup involves running it using vagrant. Unfortunately, I keep encountering the following error: [1601171008162] ERROR (32761 on local): D ...

The outer border of the Angular Material Mat Grid List is beautifully highlighted

In my project, I have a mat grid list where users can define the number of rows and columns. My goal is to display borders around each mat-grid-title cell. However, I am struggling to properly display the outermost black border for the entire mat-grid-lis ...

Transitioning a codebase from @angular-builders/custom-webpack to NX for project optimization

I need help migrating my Angular project from using "@angular-builders/custom-webpack" build targets to transitioning to an integrated NX monorepo. When I run the command npx nx@latest init --integrated, I receive the following warning: Unsupported build ...

Displaying a default input placeholder in Kendo UI Datepicker for Angular 2

I've recently implemented the [Datepicker feature from Telerik Kendo UI][1] While the datepicker functions perfectly, I have encountered a single issue where it displays undefined when the date value is not defined: [![enter image description here][ ...

Can components be SSGed individually rather than entire pages?

I am currently working with Next.js and I am wondering if there is a way to statically generate and display the database values in the header and footer components used across all pages. While getStaticProps can generate pages statically, it doesn't ...

The ngtools/webpack error is indicating that the app.module.ngfactory is missing

I'm currently attempting to utilize the @ngtools/webpack plugin in webpack 2 to create an Ahead-of-Time (AoT) version of my Angular 4 application. However, I am struggling to grasp the output generated by this plugin. Specifically, I have set up a ma ...

Undefined output in Typescript recursion function

When working with the recursion function in TypeScript/JavaScript, I have encountered a tricky situation involving the 'this' context. Even though I attempted to use arrow functions to avoid context changes, I found that it still did not work as ...

Identifying data types in arrays using TypeScript type predicates

My current approach involves a function that validates if a variable is an object and not null: function isRecord(input: any): input is Record<string, any> { return input !== null && typeof input === 'object'; } This type predica ...

Formatting text to automatically continue onto the next line without requiring scrolling through long blocks of

I have a unique Angular project with a terminal interface that functions properly, maintaining a vertical scroll and automatically scrolling when new commands are entered. However, I am struggling to get the text within the horizontal divs to wrap to the ...

Exploring the concept of rest arrays within a destructured object

Is there a way to declare c as an optional array of any type in this code snippet? const a = ({ b, ...c }: { b: string, c: ? }) => null ...

Error message: Unable to access property 'post' from undefined - Angular 2

Here is the snippet of code in my component file: import { Component, Injectable, Inject, OnInit, OnDestroy, EventEmitter, Output } from '@angular/core'; import { Http, Response, Headers, RequestOptions } from '@angular/http'; import & ...

The callback function inside the .then block of a Promise.all never gets

I'm currently attempting to utilize Promise.all and map in place of the forEach loop to make the task asynchronous. All promises within the Promise.all array are executed and resolved. Here is the code snippet: loadDistances() { //return new Prom ...

Ways to Execute the Constructor or ngOnInit Multiple Times

Here's the scenario I'm facing: I have developed an app with multiple screens. One of these screens displays a list of articles. When a user clicks on an article, they are directed to another screen that shows the details of that specific item. ...

What is the best Node version for me to use?

When downloading Node, you are given the option of choosing between LTS and Current versions. The LTS version is 4.6.0, while the current version is 6.7.0. I opted for the LTS version, which comes bundled with npm version 2.15.9. However, I encountered a ...

One parent contains two identical components, but the first component takes precedence over the second

Within my component, I have two subcomponents that are identical: <!-- Some code ... --> <app-upload-button #idBook [accept]="'image/*'" (loadend)="onImageLoaded('#this-idbook-preview')" > </app-upload-button> ...

Exploring the depths of Javascript objects using Typescript

If I have this specific dataset: data = { result: [ { id: '001', name: 'Caio B', address: { address: 'sau paulo', city: 'sao paulo', ...

What are the steps to enable generators support in TypeScript 1.6 using Visual Studio Code?

I have been working with ES6 in Visual Studio Code for some time now, but when I attempt to transition to TypeScript, I encounter errors like: Generators are only available when targeting ECMAScript 6 Even though my tsconfig.json file specifies the ES6 ...

Which is better in Angular2: defining default property values in the constructor or inline?

When it comes to creating an object class in Angular 2, the common dilemma is whether to initialize values inline or within a constructor. But what exactly is the difference between the two approaches? export class Foo { id: string; name: string = &ap ...