I'd like to be able to choose a random element from the SHAPES array, while also keeping it as const
so that the Shape
type can be used elsewhere in the code. Ideally, I want to be able to use the below randomChoice
function for both const
and non-const
arrays.
const SHAPES = [
'circle',
'square',
'triangle',
] as const;
type Shape = typeof SHAPES[number];
console.log('Available shapes are:');
for (let shape of SHAPES) {
console.log(` ${shape}`);
}
function randomChoice<T>(arr: T[]): T {
let index = Math.floor(arr.length * Math.random());
return arr[index];
}
console.log('A random shape is:');
console.log(randomChoice(SHAPES));
When I run the above, I get this error:
C:\ts>npx tsc test.ts
test.ts:18:26 - error TS2345: Argument of type 'readonly ["circle", "square", "triangle"]' is not assignable to parameter of type 'any[]'.
The type 'readonly ["circle", "square", "triangle"]' is 'readonly' and cannot be assigned to the mutable type 'any[]'.
18 console.log(randomChoice(SHAPES));
~~~~~~
And if I change the last line to this:
let choice = randomChoice(SHAPES);
console.log(choice);
I get a slightly different error:
C:\ts>npx tsc test.ts
test.ts:18:27 - error TS2345: Argument of type 'readonly ["circle", "square", "triangle"]' is not assignable to parameter of type 'unknown[]'.
The type 'readonly ["circle", "square", "triangle"]' is 'readonly' and cannot be assigned to the mutable type 'unknown[]'.
18 let choice = randomChoice(SHAPES);
~~~~~~
CodePudding user response:
Using as const
on SHAPES
declares it as a readonly
array. Remove as const
if you can, or change the function definition to accept Readonly<T[]>
(sandbox):
function randomChoice<T>(arr: Readonly<T[]>): T {
let index = Math.floor(arr.length * Math.random());
return arr[index];
}