1

I have function with generic type.

But it return an error Type 'boolean' is not assignable to type 'string'.

function testing<K, V>(array: Array<{ key: K, value: V }>): Array<V> {
    return array.map(data => data.value)
}

testing([{ key: 1, value: "one" }, { key: 2, value: true }])

How can I fix this generic type issue with keeping the type generic. Because the array is unknown and the value may have different custom type.

11
  • If it can be of any type at all, why use a generic type? Just use any, no? Commented Jan 27, 2023 at 22:37
  • We'll use that type later, so any type should be avoided Commented Jan 27, 2023 at 22:41
  • The replacement of any is unknown, it forces the caller to type check it. Commented Jan 27, 2023 at 22:44
  • 1
    Does this approach meet your needs? Commented Jan 27, 2023 at 22:45
  • But if you're returning an array of generic type <V>, but in the input array, v can be of any type, I don't know how you work around using any or unknown. Commented Jan 27, 2023 at 22:46

4 Answers 4

1

TS apparently isn't smart enough to infer V being an union type, so for tricky arguments like that you'll have to declare it explicitly.

function testing<K, V>(array: Array<{ key: K, value: V }>): Array<V> {
    return array.map(data => data.value)
}

testing<number, string | boolean>(
    [{ key: 1, value: "one" }, { key: 2, value: true }]
); // works, TS is told explicitly what V is

testing(
    [{ key: 1, value: "one" }, { key: 2, value: "two" }]
); // works, TS correctly infers string
Sign up to request clarification or add additional context in comments.

1 Comment

was able to get it working below without knowing ahead of time
0

You don't really know the type of value is. You should use unknown to force users to type check it.

I also don't see why you need key and K since they are ignored.

function testing(array: Array<{value: unknown }>): Array<unknown> {
    return array.map(data => data.value);
}

testing([{ key: 1, value: "one" }, { key: 2, value: true }])

2 Comments

"I also don't see why you need key and K since they are ignored" - try calling testing([{ key: "one", value: "one" }, { key: 2, value: "two" }]).
@mbojko That is the technical side of it. The OP potentially wants to ensure the data has a key property of the same type in every item. However, It's odd and potentially wrong that a function would enforce the type of something that it does not care about.
0

This should work:

function testing<K, V>(array: Array<{ key: K, value: V }>): Array<V> {
    return array.map(data => data.value)
}

testing<number, string | boolean>([{ key: 1, value: "one" }, { key: 2, value: true }])

Comments

0

The following will extract the type of each value and return the union:

type ArrayValueTypes<MyValueArray extends { value: unknown }[]> = {
    [K in keyof MyValueArray]: MyValueArray[K]['value']
}

const myArray = [{ key: 1, value: "one" }, { key: 2, value: true }]

function testing<T extends { value: any }[]>(array: T): ArrayValueTypes<T> {
    return array.map(data => data.value)
}

const result = testing(myArray)
// result is of type (string | boolean)[]

Typescript playground example!

1 Comment

The OP explained that they don't know all the types value could be.

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.