Find object in multiple arrays by value of specific key

Viewed 199

I need to find an object in multiple arrays by a target value and return the source value.

The data looks like this:

{
  "something": [
    {
      "type": "static",
      "source": "data-access-select",
      "target": "data-access-graphql"
    },
    {
      "type": "static",
      "source": "return-me",
      "target": "find-me"
    }
  ],
  "anything": [
    {
      "type": "static",
      "source": "data-access-page-index",
      "target": "data-access-graphql"
    }
  ]
}

So there are multiple arrays.

const depsBuffer = await readFile(
  resolve('node_modules/.cache/nx/nxdeps.json')
)
const deps = JSON.parse(depsBuffer.toString('utf-8')).dependencies

for (const [key, value] of Object.entries(deps)) {
  const res = value.find(x => x.target === 'find-me').source
  console.log(res); // expected: 'return-me'
}

But with this I do get the ts error Property 'find' does not exist on type 'unknown'

4 Answers

const deps = {
  "something": [
    {
      "type": "static",
      "source": "data-access-select",
      "target": "data-access-graphql"
    },
    {
      "type": "static",
      "source": "return-me",
      "target": "find-me"
    }
  ],
  "anything": [
    {
      "type": "static",
      "source": "data-access-page-index",
      "target": "data-access-graphql"
    }
  ]
};

const foundElement = Object.values(deps).flat().find(el => el.target === "find-me");
console.log(foundElement.source);

The reason for the error is that TypeScript does not know that value is an Array. It sees value as unknown.

Try specifying a type to describe the expected shape of the JSON

interface Dependencies {
  [key: string]: Array<{
    type: string,
    source: string, 
    target: string
  }>;
}

const depsBuffer = await readFile(
  resolve('node_modules/.cache/nx/nxdeps.json')
);
const deps = JSON.parse(depsBuffer.toString('utf-8')).dependencies as Dependencies;

for (const [key, value] of Object.entries(deps)) {
  const res = value.find(x => x.target === 'find-me').source;
  console.log(res); // expected: 'return-me'
}

You can try this code:

const source = Object.values(deps).reduce((source, array) => {
  const element = array.find(x => x.target === 'find-me');
  if (element) return element.source;
  else return source;
}, null);

or this is more similar to your code:

for (const [_, value] of Object.entries(deps)) {
  const res = value.find(x => x.target === 'find-me');
  // res is going to be undefined if in the array there is not an object with that target
  if (res) console.log(res.source);
}

Use the Array.prototype.filter() method. if the target is found, then the first element of the array is your answer.

const array = "Your array here";
let result;
for (var key in array) {
    result = array[key].filter(r => r.target === "find-me");
    if(result.length > 0){
        break;
    }
}

if(result.length > 0){
    console.log(result[0].source);
}
Related