'Inconvenience when working `as const` arrays - readonly T[] not assignable to T[] - how to remove readonly modifier from array [duplicate]

I keep running into this problem all the time (playground link):

const arr = [1,2,3] as const

const doSomethingWithNumbers = <T extends number[]>(numbers: T) => {}

doSomethingWithNumbers(arr)
//                     ^
// Argument of type 'readonly [1, 2, 3]' is not assignable to parameter of type 'number[]'.
//  The type 'readonly [1, 2, 3]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.

I know I can modify the function to also take readonly arrays:

export type AllowReadonly<T extends any[]> = T | readonly T[number][]

const doSomethingWithNumbers = <T extends <number[]>>(numbers: AllowReadonly<T>) => {}

but then I just run into the exact same problem inside doSomethingWithNumbers, since numbers parameter can now also be readonly.

What is a good way to tackle this issue?



Solution 1:[1]

EDIT:

I found this even better answer in a question that aims to remove readonly modifier not only from arrays, but also objects.

This is the approach that works for both arrays and objects: playground link


Original answer:

One way I found is using this function to remove the readonly modifier when passing into the function:

const removeReadonly = <T extends any>(arr: T[] | readonly T[]): T[] => arr as T[]

usage (playground link):

const arr = [1,2,3] as const

const doSomethingWithNumbers = <T extends number[]>(numbers: T) => {}

const removeReadonly = <T extends any>(arr: T[] | (readonly T[])): T[] => arr as T[];

const nonReadonlyArr = removeReadonly(arr)  // (1 | 2 | 3)[];
doSomethingWithNumbers(nonReadonlyArr)      // No error;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1