Ronald Ruzicka
Ronald Ruzicka

Reputation: 204

Create union of unique array items from union of types (typescript)

I'd like to ask, is it possible to declare an array of unique types from union of those types?

I have this type Value:

type Value = string | number

Then I created type Values like this:

type Values = Value[]

but that creates a type:

type Values = (string|number)[]

but how can I achieve this from the type Value?

type Values = string[] | number[]

Because basically I have a function that renders checkbox-es for table filters. That checkbox will always have either string or number as a value.

Then when you click on a checkbox, it adds that value to an array. For example, you have a column firstName and you add two names to that filter. It then becomes an array of string or array of number: string[] | number[] which would represent my type Values.

So is there a way to create type Values from type Value?

I created this sample sandbox just to compare those types.

Thanks for any input!

Upvotes: 2

Views: 1842

Answers (2)

Nathan Chappell
Nathan Chappell

Reputation: 2436

These solutions are not satisfactory to me. In the first case, I must explicitly mention the type of element I'm expecting in the array. In the second, I must enumerate all array types I'm interested in (what I'm trying to avoid in the first place! Besides, I have the union type, I want the array types - it's not a matter of preference)

Anyways, after playing around a bit I figured out one way to make it work. Then I went back to the documentation and realized that they actually use this exact problem as an example...

type ValueTypes = string | number
type ToArray<Type> = Type extends any ? Type[] : never;

const a1: ToArray<ValueTypes> = ['a','b'] // okay
const a2: ToArray<ValueTypes> = [1, 2]    // okay
const a3: ToArray<ValueTypes> = ['a', 2]  // error (i.e. success)

Upvotes: 1

Orelsanpls
Orelsanpls

Reputation: 23515

I would choose of restricted templating

type Values<T extends string | number> = T[];

const myArr: Values<string> = [
    'foo',
    'bar',
];

const myArr2: Values<number> = [
    1,
    2,
];

Or use overloaded types (let typescript decide the type depending on what's inside of the array)

type ValueTypeA = string[];
type ValueTypeB = number[];

type Values = ValueTypeA | ValueTypeB;

const myArr: Values = [
    'foo',
    'bar',
];

const myArr2: Values = [
    1,
    2,
];

Upvotes: 1

Related Questions