Home > database >  TypeScript error with Object.fromEntries from fetched data
TypeScript error with Object.fromEntries from fetched data

Time:12-24

requests = { name: url, name: url, ...} I've tried to fetch every url and return { name: data, name: data, ...}

Code

async function fetchMovies(url: string) {
  const data = await fetch(baseURL   url).then((r) => r.json());
  return data.results;
}

export const getMovies = createAsyncThunk("movies/getMovies", async () => {
  const responses = Object.entries(requests).map(async ([key, value]) => {
    try {
      const response = await fetchMovies(value);
      return [key, response];
    } catch (e: unknown) {
      if (e instanceof Error) {
        console.log(e.message);
      }
    }
  });

  const results = await Promise.all(responses);
  console.log(results); // [[string, SomeType[]], [string, SomeType[]], ...]
  return Object.fromEntries(results); // error
});

console.log(results)

Array (8)
 0 ["netflixOriginals", Array] (2)
 1 ["trending", Array] (2)
 2 ["topRated", Array] (2)
 3 ["action", Array] (2)
 4 ["comedy", Array] (2)
 5 ["horror", Array] (2)
 6 ["romance", Array] (2)
 7 Array (2)
   0 "documentary"
   1 [Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, …] (20)

Error

TS2769: No overload matches this call.
  Overload 1 of 2, '(entries: Iterable<readonly [PropertyKey, any]>): { [k: string]: any; }', gave the following error.
    Argument of type '(any[] | undefined)[]' is not assignable to parameter of type 'Iterable<readonly [PropertyKey, any]>'.
      The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
        Type 'IteratorResult<any[] | undefined, any>' is not assignable to type 'IteratorResult<readonly [PropertyKey, any], any>'.
          Type 'IteratorYieldResult<any[] | undefined>' is not assignable to type 'IteratorResult<readonly [PropertyKey, any], any>'.
            Type 'IteratorYieldResult<any[] | undefined>' is not assignable to type 'IteratorYieldResult<readonly [PropertyKey, any]>'.
              Type 'any[] | undefined' is not assignable to type 'readonly [PropertyKey, any]'.
                Type 'undefined' is not assignable to type 'readonly [PropertyKey, any]'.
  Overload 2 of 2, '(entries: Iterable<readonly any[]>): any', gave the following error.
    Argument of type '(any[] | undefined)[]' is not assignable to parameter of type 'Iterable<readonly any[]>'.
      The types returned by '[Symbol.iterator]().next(...)' are incompatible between these types.
        Type 'IteratorResult<any[] | undefined, any>' is not assignable to type 'IteratorResult<readonly any[], any>'.
          Type 'IteratorYieldResult<any[] | undefined>' is not assignable to type 'IteratorResult<readonly any[], any>'.
            Type 'IteratorYieldResult<any[] | undefined>' is not assignable to type 'IteratorYieldResult<readonly any[]>'.
              Type 'any[] | undefined' is not assignable to type 'readonly any[]'.
                Type 'undefined' is not assignable to type 'readonly any[]'.
    22 |   const results = await Promise.all(responses);
    23 |   console.log(results);
  > 24 |   return Object.fromEntries(results);
       |                             ^^^^^^^
    25 | });
    26 |

The only solution I have found is results:any[]. I'm not very good with TS, I've tried everything I know. Sorry for the stupid question

CodePudding user response:

Since you didn't specify type to responses object, it will automatically detect based on the return from its operation.

In your case,

  • you returned a array in try block which is any[]
  • nothing is returned in catch block so it may be undefined also

Hence, the responses type would be (any[] | undefined)[]

Do something about this, (like returning [key,value] inside catch also) then the type would be any[][]. Object.fromEntries() will accept this type.

CodePudding user response:

The problem comes from the try catch. When fetchMovies throws an exception, you don't return anything in your catch. Depending on your usage whether you need the data or to really throw an error.

If you really need the data even when it throws. You can do the following:

try {
      const response = await fetchMovies(value);
      return [key, response];
    } catch (e: unknown) {
      if (e instanceof Error) {
        console.log(e.message);
      }
      return [key, e];
    }
  • Related