1

As shown elsewhere (e.g. TypeScript String Union to String Array) it is easy to define union type from tuple:

const arr = ["foo", "bar"] as const
const Item = typeof arr[number]

Unfortunately I cannot use arr where Item[] is required - the type of arr is readonly ["foo", "bar"], and even direct type cast results in typescript error TS2352.

Typescripts suggests to cast to unknown first - it works but it looks confusing and kind of defeats the whole purpose of type-safe array constant:

const _arr: Item[] = (arr as unknown) as Item[]

Is there any better way to have both the full list of options as Item[] and Item union type without repeating the actual options, other than above double cast?

esp
  • 7,314
  • 6
  • 49
  • 79

2 Answers2

2

What you want to do is type-unsafe. Given

const arr = ["foo", "bar"] as const

If you could type the same arr as Item[] when using it somewhere, and then (for example) pass it to a function which accepts Item[] as a parameter, that function could then do:

arrayParameter.push('foo');

which would be perfectly fine because the parameter would still remain an Item[]. But the original type is now incorrect, because the mutated arr is no longer ["foo", "bar"] as const - rather, it has 3 items.

Slice (or otherwise somehow shallow copy) the array first if you want to use it as a generic Item[]. There's no other way to do this which would be type-safe.

const arr = ['foo', 'bar'] as const;
type Item = typeof arr[number];
const arrItems: Item[] = arr.slice();
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
1

if your function takes readonly string[] this as input, then you can pass existing arr, I know you might not have a control or change the function signature, but just throwing this out in case it helps

const tuple = ['foo', 'bar'] as const


function println(arr: readonly string[]) {
  console.log(arr)
}

println(tuple)
println(['a', 'b', 'c'])
Pritam Kadam
  • 2,388
  • 8
  • 16