-4

by 23 lines I get this Property 'title' does not exist on type 'faceProductList | faceProductList[]'Why does such an error occur as to solve it?

code

interface faceProductList {

  readonly title: string;
  readonly price: string;
  readonly prodState: string;
  readonly shipping: string;
  readonly sold: string;
  readonly src: string;
  readonly id: string;
  readonly to: string;
}

class Server {
    private url: string = 'https://foo0022.firebaseio.com/';
    public async request(id: string): Promise<(faceProductList[] | faceProductList)[]> {
        const res = await fetch(`${this.url}${id}`);
        const resArr: (faceProductList[] | faceProductList)[]  = await res.json();
        return resArr;
    }
    public async handler(id: string, valueSearch: string) { 
        await this.request(id)
        .then((array) => { 
            if(id){ 
              return  array.filter(({title}) => title.includes(valueSearch))
            }

            })
    }
}
x0n
  • 51,312
  • 7
  • 89
  • 111
Edgar
  • 6,022
  • 8
  • 33
  • 66
  • 1
    Show your [mcve] as searchable, copyable text, along with any explanation of what you are trying to do and any results or errors you get. See [ask]. –  Feb 26 '19 at 21:10

2 Answers2

1

Your request will return a (faceProductList[] | faceProductList)[] which means each array item is either a faceProductList or an array of faceProductList. The error is telling you that the filter doesn't work if item being filtered is an array.

Depending on your exact requirements, you could flatten the result set before you filter:

return array
  .reduce((acc: faceProductList[], cur) => (Array.isArray(cur) ? acc.concat(cur) : acc.push(cur), acc), [])
  .filter(({ title }) => title.includes(valueSearch))

Note: You could also use the built-in flat method, but see this answer.

Or you could rewrite your filter condition to handle either case:

return array
  .filter((item) => Array.isArray(item)
    ? item.some(({ title }) => title.includes(valueSearch))
    : item.title.includes(valueSearch))

You can write this a bit more cleanly if you flatten it first and save it to a separate variable:

const flatArray = array.reduce((acc: faceProductList[], cur) => (Array.isArray(cur) ? acc.concat(cur) : acc.push(cur), acc), []);
if (id) {
  return flatArray.filter(({ title }) => title.includes(valueSearch));
}

return flatArray;
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • Here is my common [link](https://codesandbox.io/s/rlm8nw5won) I'm trying to fix it but it doesn’t work – Edgar Feb 27 '19 at 06:04
  • @ArnifridPegasus flatten the array as I show in my answer. You'll have to make sure both branches return a valid type. See my updated answer. – p.s.w.g Feb 27 '19 at 13:51
-2

Well, it's true -- the value (faceProductList[] | faceProductList)[] which - when unrolled in filter - may be a element or an array of elements doesn't definitively have a title property. I suggest ensuring request always return an array. Test the return from firebase to see if it's a single element, if it is, then stuff into into an array and return that instead. Change your signatures to match expectations.

x0n
  • 51,312
  • 7
  • 89
  • 111
  • 1
    Please provide answers that do not require clarification from the OP. – grooveplex Feb 26 '19 at 21:18
  • @grooveplex What clarification is expected? I do not follow your logic. – x0n Feb 26 '19 at 21:19
  • 1
    I assuming the API was fixed and OP just had to work around it, but if this is not the case, and the awkward typing is just accidental, this would actually be the more correct answer. – p.s.w.g Feb 26 '19 at 21:29