Definitelytyped: [@types/jest] jest-each methods should allow done-callback style tests

Created on 10 Apr 2019  路  5Comments  路  Source: DefinitelyTyped/DefinitelyTyped

  • [x] I tried using the @types/xxxx package and had problems.
  • [x] I tried using the latest stable version of tsc. https://www.npmjs.com/package/typescript
  • [x] I have a question that is inappropriate for StackOverflow. (Please ask any appropriate questions there).
  • [x] [Mention](https://github.com/blog/821-mention-somebody-they-re-notified) the authors (see Definitions by: in index.d.ts) so they can respond.

    • Authors: @niedzielski

Tests that use the final parameter to it.each() in order to end the test using Jest's DoneCallback are incompatible with the templated types for it.each().

Incredibly simple but contrived example:

it.each<number>([1, 2, 3])('dummy: %d', (num, done) => {
    done();
});

TypeScript complains that done is a number, not a function.

Most helpful comment

Meanwhile, specifying the generic as any and manually typing everything is the only way I guess:

    it.each<any>([
      [
        [1, 2, 3],
        ['1', '2', '3']
      ],
      [
        [4, 5, 6],
        ['4', '5', '6']
      ],
    ] as [number[], string[]][])(
      'should do stuff',
      (numbers: number[], strings: string[], done: jest.DoneCallback) => {
        someAsyncFn(() => {
          done();
        });
      }
    );

All 5 comments

I don't know how to declare a function with an argument after a spread argument.

The current implementation is:

    interface Each {
        // Exclusively arrays.
        <T extends any[]>(cases: ReadonlyArray<T>): (
            name: string,
            fn: (...args: T) => any,
            timeout?: number
        ) => void;
        // Not arrays.
        <T>(cases: ReadonlyArray<T>): (
            name: string,
            fn: (...args: T[]) => any,
            timeout?: number
        ) => void;
        (cases: ReadonlyArray<ReadonlyArray<any>>): (
            name: string,
            fn: (...args: any[]) => any,
            timeout?: number
        ) => void;
        (strings: TemplateStringsArray, ...placeholders: any[]): (
            name: string,
            fn: (arg: any) => any,
            timeout?: number
        ) => void;
    }

I think what you want is:

    interface Each {
        // Exclusively arrays.
        <T extends any[]>(cases: ReadonlyArray<T>): (
            name: string,
            fn: (...args: T, done: DoneCallback) => any,
            timeout?: number
        ) => void;
        // Not arrays.
        <T>(cases: ReadonlyArray<T>): (
            name: string,
            fn: (...args: T[], done: DoneCallback) => any,
            timeout?: number
        ) => void;
        (cases: ReadonlyArray<ReadonlyArray<any>>): (
            name: string,
            fn: (...args: any[], done: DoneCallback) => any,
            timeout?: number
        ) => void;
        (strings: TemplateStringsArray, ...placeholders: any[]): (
            name: string,
            fn: (arg: any, done: DoneCallback) => any,
            timeout?: number
        ) => void;
    }

But only the last overload is valid in current TypeScript. However, in that case, the parameter typing is lost.

Yeah I don't believe there's a good way of doing this right now with TypeScript unfortunately. :(

Need this too.

Can be implemented when https://github.com/Microsoft/TypeScript/issues/1360 is addressed

Meanwhile, specifying the generic as any and manually typing everything is the only way I guess:

    it.each<any>([
      [
        [1, 2, 3],
        ['1', '2', '3']
      ],
      [
        [4, 5, 6],
        ['4', '5', '6']
      ],
    ] as [number[], string[]][])(
      'should do stuff',
      (numbers: number[], strings: string[], done: jest.DoneCallback) => {
        someAsyncFn(() => {
          done();
        });
      }
    );

The workaround I use is specifying two types and then explicitly typing the parameters like this:

 it.each<number | jest.DoneCallback>([1, 2, 3])(
    'dummy: %d',
    (num: number, done: jest.DoneCallback) => {
        done();
    },
);

It's a late reply but I hope it helps anyone stumbling on this issue

Was this page helpful?
0 / 5 - 0 ratings