typescript - Kan inte återskapa doc-exempel för Jest-anpassad matcher: egenskapen finns inte på typ "Expect"


Jag försöker skapa en anpassad hjälpare matcher som kan användas som arrayContaining direkt från expect-objektet utan att skicka ett värde att jämföra med.

I den officiella dokumentationen för expect.extend() finns ett exempel som passar mina behov:

export {}

declare global {
  namespace jest {
    interface Matchers<R> {
      toBeWithinRange(a: number, b: number): R;
    }
  }
}

expect.extend({
  toBeWithinRange(received, floor, ceiling) {
    const pass = received >= floor && received <= ceiling;
    if (pass) {
      return {
        message: () =>
          `expected ${received} not to be within range ${floor} - ${ceiling}`,
        pass: true,
      };
    } else {
      return {
        message: () =>
          `expected ${received} to be within range ${floor} - ${ceiling}`,
        pass: false,
      };
    }
  },
});

test('numeric ranges', () => {
  expect(100).toBeWithinRange(90, 110);
  expect(101).not.toBeWithinRange(0, 100);
  expect({apples: 6, bananas: 3}).toEqual({
    apples: expect.toBeWithinRange(1, 10), // <-- What I need
    bananas: expect.not.toBeWithinRange(11, 20),
  });
});

Jag kan dock inte återskapa exemplet ens med en minimal uppsättning. Jag fick fortfarande följande fel:

apples: expect.toBeWithinRange(1, 10), // property 'toBeWithinRange' doesn't exist on type 'Expect'. (ts2339)

Jag installerade @types/jest och lade till den globala deklarationen utan framgång.

Vilken del av konfigurationen saknar jag?

Svar #1

Jag saknade en typtolkning för det direkta anropet till expect.toBeWithinRange(). Här är det slutliga fungerande exemplet för mig:

// customMatcher.ts

declare global {
  namespace jest {
    interface Matchers<R> {
      toBeWithinRange(a: number, b: number): R;
    }
    interface Expect {
      toBeWithinRange(a: number, b: number): any;
    }

    interface InverseAsymmetricMatchers {
      toBeWithinRange(a: number, b: number): any;
    }
  }
}

export function toBeWithinRange(received, floor, ceiling) {
  const pass = received >= floor && received <= ceiling;
  if (pass) {
    return {
      message: () =>
        `expected ${received} not to be within range ${floor} - ${ceiling}`,
      pass: true,
    };
  } else {
    return {
      message: () =>
        `expected ${received} to be within range ${floor} - ${ceiling}`,
      pass: false,
    };
  }
}

expect.extend({
  toBeWithinRange,
});

Och för att använda den anpassade matcharen i en annan fil behöver du importera dess definition:

// customMatcher.spec.ts

import './customMatcher.ts';

test('numeric ranges', () => {
  expect(100).toBeWithinRange(90, 110);
  expect(101).not.toBeWithinRange(0, 100);
  expect({apples: 6, bananas: 3}).toEqual({
    apples: expect.toBeWithinRange(1, 10), // <-- What I need
    bananas: expect.not.toBeWithinRange(11, 20),
  });
});