将const数组传递给泛型函数时出错



我希望能够从SHAPES数组中选择一个随机元素,同时将其保持为const,以便Shape类型可以在代码的其他地方使用。理想情况下,我希望能够对const和非const数组使用下面的randomChoice函数。

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));

当我运行上面的代码时,我得到了这个错误:

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));
                            ~~~~~~

如果我把最后一行改成这样:

let choice = randomChoice(SHAPES);
console.log(choice);
我得到一个稍微不同的错误:
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);
                             ~~~~~~

SHAPES上使用as const声明它为readonly数组。如果可以,删除as const,或者更改函数定义以接受Readonly<T[]> (sandbox):

function randomChoice<T>(arr: Readonly<T[]>): T {
  let index = Math.floor(arr.length * Math.random());
  return arr[index];
}

最新更新