我在将JS文件转换为TS时遇到了以下问题,示例与下面的代码类似:
let arr = Float32Array(3)
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
let min_value = Math.min.apply(null, arr);
在本例中,TypeScript将产生一个错误,并显示以下消息:
Argument of type 'Float32Array' is not assignable to parameter of type 'number[]'.
Type 'Float32Array' is missing the following properties from type 'number[]': pop, push, concat, shift, and 5 more.
假设arr
是性能敏感的变量,不应该转换为number[]
,欺骗编译器工作的最明显的解决方案是转换变量:
let min_value = Math.min.apply(null, arr as unknown as number[]);
在这种情况下,apply
不能接收Float32Array
参数的具体原因/危险性是否存在?
Function.protype.apply((声明arguments
参数可以是任何类似数组的对象。
Typed数组是类似数组的对象,因此它们应该被apply
方法接受。
此外,Math.min规范指出,它的参数甚至不需要是数字:
给定零个或多个参数,此函数会对每个参数调用ToNumber,并返回最小的结果值。
了解了以上所有内容,您尝试做的事情看起来是正确的,而且看起来像是TypeScript错误。
至于为什么会发生这种情况,目前Math.min
和CallableFunction.apply
的定义如下:
min(...values: number[]): number;
apply<T, A extends any[], R>(
this: (this: T, ...args: A) => R,
thisArg: T,
args: A
): R;
很可能这两个定义都需要根据标准进行调整
编辑:可能只有apply
定义需要更改为类似的内容
apply<T, A extends Iterable<AT>, AT, R>(
this: (this: T, ...args: AT[]) => R,
thisArg: T,
args: A
): R;
或者更准确地说,应该使用ArrayLike<AT>
而不是Iterable<AT>
,但为了使上述功能发挥作用,ArrayLike
需要从Iterable
扩展
TypeScript安全的编写方法是:
let min_value = Math.min(...arr);
其编译为Math.min.apply(Math, arr);