0

I am trying to compare if an item exists in another array by checking a common property value. For the below code it is throwing the below error:

TS2367: This condition will always return 'false' since the types 'U[K]' and 'T[K]' have no overlap.

 const sourceArray = [{requestId: "1", name: "henry"},{requestId: "2", name: "bob"}] 
 const arrayListToCompareWith = [{requestId: "1", age: 30}, {requestId: "9", age: 40}]
 const commonItems = getItemsInSourceArrayWhichArePresentInArrayToBeComparedWith(sourceArray,arrayListToCompareWith, "requestId" )
 
 function getItemsInSourceArrayWhichArePresentInArrayToBeComparedWith<
    T,
    U,
    K extends keyof T & keyof U,
  >(
    sourceArray: T[],
    arrayListToCompareWith: U[],
    comparisonKey: K, // "requestId"
  ) {
    const itemsInSourceArrayWhichAreNotPresentInArrayToBeComparedWith: T[] =
      sourceArray.filter((sourceArrayItem: T): boolean => {
        const { [comparisonKey]: sourceArrayItemComparisonKeyValue } = sourceArrayItem; sourceArrayItemComparisonKeyValue
        const itemExistsInTheArrayWeAreComparingWith: boolean =
          arrayListToCompareWith.some((itemToCompareWith: U): boolean => {
            const comparisonValueInItemToCompareWith = itemToCompareWith[comparisonKey]; // U[K]
            const comparisonValueInSource = sourceArrayItemComparisonKeyValue; //T[K]
            // TS2367: This condition will always return 'false' since the types 'U[K]' and 'T[K]' have no overlap.
            const check = comparisonValueInItemToCompareWith === comparisonValueInSource;
            return check;
          });
        return itemExistsInTheArrayWeAreComparingWith;
      });
    return itemsInSourceArrayWhichArePresentInArrayToBeComparedWith;
  }

Below is the TS playground link for the above code problem:

TS Playground link to run the code

3
  • 1
    Are these your real function and variable names? Why are they miles long? Commented Oct 17, 2021 at 17:03
  • Thinking it will help in readability, and make others understand what I am trying to convey. Commented Oct 17, 2021 at 17:28
  • Shorter names make for more readable code, all else being equal. Commented Oct 17, 2021 at 17:29

1 Answer 1

1

The problem is that you didn't tell Typescript that there is any relationship between T and U, in particular you didn't say that they must have the same value type for the property K.

Actually there is no need for your second type parameter U - all we need to say is that the second array contains objects which have a key K with the same value type as T does. This can be more simply written as Pick<T, K>.

function filterByKey<T, K extends keyof T>(arr: T[], keysToKeep: Pick<T, K>[], key: K) {
  return arr.filter(
    item => keysToKeep.some(
      otherItem => item[key] === otherItem[key]
    )
  );
}

Playground Link

Sign up to request clarification or add additional context in comments.

5 Comments

I am not sure how typescript playground is not throwing an error because when you pass keysToKeep array which has an age property as a mandatory parameter. But with Pick<T,K> you will get the type which does not have age. I clearly demonstrated the issue in the below playground link. TO Summarize: 1.With Pick<T,K> keysToKeep variable will have type {requestId: string, name: string}. 2. But keysToKeep has type KeysToKeep with age as a mandatory params. 3. Not sure why TS playground is not throwing an error Correct me if my understanding is wrong
The Typescript Playground link in my answer does not show an error, because there is no error. The array keysToKeep is assignable to the type Pick<T, K>[] because it is an array whose members are assignable to the type Pick<T, K>. They are assignable to the type Pick<T, K> because they have all the properties required in order to be assignable to that type; the fact that they have extra properties is irrelevant.
Thank you. I had to understand typescript soundness to understand your solution on why Pick<T,K> is working and not throwing an error. Soundness link : typescriptlang.org/docs/handbook/… Will this solution work if ** strictFunctionTypes** is enabled?
The Playground link has strict mode enabled, so yes, it works with strictFunctionTypes and all the other strict config settings. (strictFunctionTypes in particular has literally no effect here.) This isn't unsound behaviour, it's just structural subtyping.
thank you for your help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.