Home > front end >  Type script error reduce when loop on array
Type script error reduce when loop on array

Time:10-24

I have an array of objects like this

type AnyType = {
  name: 'A' | 'B' | 'C';
  isAny:boolean;
};

const myArray :AnyType[] =[
  {name:'A',isAny:true},
  {name:'B',isAny:false},
]

I want to run on myArray with reduce to get array for name only

const namesArray=myArray.reduce<AnyType['name'][]>((a,b)=>{
  return b.name;
},[])

but I get a typeScript error

(parameter) b: AnyType
BugFinder: No overload matches this call.BugFinder: 
  Overload 1 of 6, '(callbackfn: (previousValue: ("A" | "B" | "C")[], currentValue: AnyType, currentIndex: number, array: AnyType[]) => ("A" | "B" | "C")[], initialValue: ("A" | "B" | "C")[]): ("A" | ... 1 more ... | "C")[]', gave the following error.BugFinder: 
    Argument of type '(a: ("A" | "B" | "C")[], b: AnyType) => "A" | "B" | "C"' is not assignable to parameter of type '(previousValue: ("A" | "B" | "C")[], currentValue: AnyType, currentIndex: number, array: AnyType[]) => ("A" | "B" | "C")[]'.BugFinder: 
      Type '"A" | "B" | "C"' is not assignable to type '("A" | "B" | "C")[]'.BugFinder: 
        Type '"A"' is not assignable to type '("A" | "B" | "C")[]'.BugFinder: 
  Overload 2 of 6, '(callbackfn: (previousValue: ("A" | "B" | "C")[], currentValue: AnyType, currentIndex: number, array: AnyType[]) => ("A" | "B" | "C")[], initialValue: ("A" | "B" | "C")[]): ("A" | ... 1 more ... | "C")[]', gave the following error.BugFinder: 
    Argument of type '(a: ("A" | "B" | "C")[], b: AnyType) => "A" | "B" | "C"' is not assignable to parameter of type '(previousValue: ("A" | "B" | "C")[], currentValue: AnyType, currentIndex: number, array: AnyType[]) => ("A" | "B" | "C")[]'.BugFinder: 
      Type '"A" | "B" | "C"' is not assignable to type '("A" | "B" | "C")[]'.BugFinder: 
        Type '"A"' is not assignable to type '("A" | "B" | "C")[]'.

playground

CodePudding user response:

The return value is an array:

const NamesArray = myArray.reduce<AnyType["name"][]>(
  (a, { name }) => [...a, name],
  []
);

Another way using Array#map:

const NamesArray = myArray.map<AnyType["name"]>(({ name }) => name);

CodePudding user response:

If you just wanna 'map' the array to a different array, you should use the myArray.map method;
But if you want to specifically use reduce, let's say to also filter in the process, then the problem is with the reducer callback.
The reducer should return the accumulator, which in your case is an array of names;
This is the error TS is giving you, you're returning a name (of the current element) instead of an array of names.

This is an example of a reduce which maps and filters at the same time:

const namesArray = myArray.reduce<AnyType['name'][]>( ( accumulatorArr, currentValue ) => {
  if ( currentValue.isAny ) {
    accumulatorArr.push( currentValue.name );
  }
  return accumulatorArr;
}, [] );

CodePudding user response:

If you want to do it using Array.reduce(), then this will be useful. But as @majed Badawi mentioned, we can do it using Array.map() easily.

interface AnyType {
  name: 'A' | 'B' | 'C';
  isAny: boolean;
}

const myArray: AnyType[] = [
  { name: 'A', isAny: true },
  { name: 'B', isAny: false },
];

const namesArray = myArray.reduce((a, b) => {
  a.push(b.name);
  return a;
}, [] as string[]);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

NOTE: I did some changes to your type declaration as well. This is the way that I preferred to use it. Please change it to your form if you prefer that way!

CodePudding user response:

Try this:

const NamesArray=myArray.reduce<AnyType['name']|[]>((a:AnyType['name']|[],b:AnyType)=>{ 
  return b.name;
},[])
  • Related