Alexander Mills
Alexander Mills

Reputation: 99980

Missing index signature in type Array<string> with TypeScript

I am seeing this error with TypeScript:

enter image description here

The code itself just looks like this:

let fn =  function (transformPaths: Array<string>, cb: Function) {

    async.mapLimit(transformPaths, 5, function (t: string, $cb: Function) {

         // ....

    }, cb);

};

The error message is:

TS2345: Argument of type 'string[]' is not assignable to parameter of type 'Dictionary<{}>'. Index signature is missing in type 'string[]'.

How can I correct this? As you can see from the screenshot, the typings from the async library do not like a plain array of strings being passed as the first argument to async.mapLimit, but why?

I am 99% certain I need to add an index signature to the array of strings, but how do I do that?

Here is something that "compiles" but I don't know if it's correct (this doesn't seem to be helping anyone):

export interface ISumanTransformPaths extends Array<string> {
  [index:string]: Object
}

now when I use (transformPaths: ISumanTransformPaths), then it compiles, but I am not sure if this correct.

Upvotes: 2

Views: 1198

Answers (2)

Alexander Mills
Alexander Mills

Reputation: 99980

Thanks Nitzan for confirming that @types/async is probably correct. This solved the problem:

before:

 let fn = function (transformPaths: Array<string>, cb: Function) {

    async.mapLimit(transformPaths, 5, function (t: string, cb: Function){

     // problem...does not compile

    }, cb);
 } 

after: (look carefully, there is just one change)

  let fn = function (transformPaths: Array<string>, cb: AsyncResultArrayCallback<Error,Array<any>>) {

        async.mapLimit(transformPaths, 5, function (t: string, cb: Function) {

        // now it compiles!

        }, cb);

   };

Upvotes: 0

Nitzan Tomer
Nitzan Tomer

Reputation: 164129

The signatures for this method are:

mapLimit<T, R, E>(arr: T[] | IterableIterator<T>, limit: number, iterator: AsyncResultIterator<T, R, E>, callback?: AsyncResultArrayCallback<R, E>): void;
mapLimit<T, R, E>(arr: Dictionary<T>, limit: number, iterator: AsyncResultIterator<T, R, E>, callback?: AsyncResultArrayCallback<R, E>): void;

So it can work with a Dictionary or an array/IterableIterator.
I'm not sure why the compiler infers the 2nd signature instead of the first, but maybe because the callback you pass it should be the 4th argument, while the 3rd needs to be an iterator.

Upvotes: 3

Related Questions