function matchItem(item, words, keys) {

  const {
    matchedWords,
    tokens
  } = keys.reduce((result, key) => {
    const itemValue = item[ key ];

    const {
      tokens,
      matchedWords
    } = isArray(itemValue) ? (
      itemValue.reduce(
        (result, itemString) => {
          const { tokens, matchedWords } = matchString(itemString, words);

          return {
            tokens: [ ...result.tokens, tokens ],
            matchedWords: {
              ...result.matchedWords,
              ...matchedWords
            }
          };
        },
        {
          matchedWords: {},
          tokens: []
        }
      )
    ) : (
      matchString(itemValue, words)
    );

    return {
      tokens: {
        ...result.tokens,
        [ key ]: tokens,
      },
      matchedWords: {
        ...result.matchedWords,
        ...matchedWords
      }
    };
  }, {
    matchedWords: {},
    tokens: {}
  });

  // only return result if every word got matched
  if (Object.keys(matchedWords).length !== words.length) {
    return null;
  }

  return tokens;
}
Match an item and return tokens in case of a match.

@param {SearchItem} item element to be matched
@param {string[]} words words from search pattern to find
@param {string[]} keys keys to search in the item

@returns {Record<string, Tokens>}