1

I'm trying to write some generic array utility functions, but when I try calling one from another, the compiler seems to cast the generic to any[] and gives me this error:

Type 'any[]' is not assignable to type 'T'.

My code:

type UnwrapArray<T extends any[]> = T extends (infer G)[] ? G : never;

function removeFromArray<T extends any[]>(
  array: T,
  value: UnwrapArray<T>
) {
  return array.filter(other => other !== value);
}

function toggleArrayValue<T extends any[]>(array: T, value: UnwrapArray<T>): T {
  if(array.includes(value)) {
    return removeFromArray<T>(array, value);
  } else {
    return [...array, value];
  }
}

The specific lines giving me trouble are these:

return removeFromArray<T>(array, value);

And

return [...array, value];

I've found I can add as T to a bunch of stuff and it will compile successfully, but it seems like the compiler should figure this out on its own.

1 Answer 1

2

You assume T extends any[] will mean T is an array, and any new array will be assignable to T. This is not true.

Consider the following:

const myArr = Object.assign([1, 2, 3], {
    extraProp : 1
})

toggleArrayValue(myArr, 1).extraProp // ts says this should be here where is my extraProp

extends any[] is the lower bound on what T can be, but it can be anything that inherits array (or a tuple but that is another can of worms of why this can't work)

I am not sure at least from your sample code why you need T to be an array. You can express what you are trying to do without this:

function removeFromArray<T>(
    array: T[],
    value: T
) {
    return array.filter(other => other !== value);
}

function toggleArrayValue<T>(array: T[], value: T): T[] {
    if (array.includes(value)) {
        return removeFromArray<T>(array, value);
    } else {
        return [...array, value];
    }
}

Maybe your actual code is more complex, if so post that (maybe in a different question) and we can see if we can find a better solution than an unsafe type assertion.

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

1 Comment

Thanks! This works perfectly and your explanation makes a lot of sense.

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.