使用数组和TypedArray重载Typescript中的递归函数
我有一个带有2个重载的递归函数:使用数组和TypedArray重载Typescript中的递归函数,typescript,generics,recursion,overloading,Typescript,Generics,Recursion,Overloading,我有一个带有2个重载的递归函数: export function select( array: Float32Array, first: number, nth: number, last: number, comp: (a: number, b: number) => boolean, ): void; export function select<T>( array: T[], first: number, nth: number, la
export function select(
array: Float32Array,
first: number,
nth: number,
last: number,
comp: (a: number, b: number) => boolean,
): void;
export function select<T>(
array: T[],
first: number,
nth: number,
last: number,
comp: (a: T, b: T) => boolean,
): void;
export function select<T>(
array: Float32Array | T[],
first: number,
nth: number,
last: number,
comp: (a: number | T, b: number | T) => boolean,
): void {
// Implementation of Floyd-Rivest algorithm
// Some code
select(array, newFirst, nth, newLast, comp);
// Some code
}
导出功能选择(
数组:Float32Array,
第一:数字,
N:号码,
最后:号码,,
comp:(a:number,b:number)=>布尔值,
):无效;
导出功能选择(
数组:T[],
第一:数字,
N:号码,
最后:号码,,
comp:(a:T,b:T)=>布尔值,
):无效;
导出功能选择(
数组:Float32Array | T[],
第一:数字,
N:号码,
最后:号码,,
comp:(a:number | T,b:number | T)=>布尔值,
):无效{
//Floyd-Rivest算法的实现
//一些代码
选择(数组、新第一个、第n个、新最后一个、复合);
//一些代码
}
Typescript在实现中递归调用select
函数时抱怨变量array
:
类型为“Float32Array | T[]”的参数不能分配给类型为“(number | T)[]”的参数
首先,我真的不明白为什么typescript试图将参数数组的类型与不同签名中不存在的类型(number | t)[
进行比较。它是否尝试将数组
的类型与comp
函数的参数类型进行比较
当然,我可以在实现签名中用任何
替换参数数组
的类型,它是有效的,但我想知道是否有更好的方法来处理这种情况。问题是实现重载(即最后一个)不能直接调用,因此,当递归调用函数时,类型必须与两个重载中的一个兼容,并且联合与这两个重载中的任何一个都不兼容(typescript不会尝试组合签名以允许传入联合)
这种情况下最简单的解决方案是复制实现签名:
export function select(
array: Float32Array,
first: number,
nth: number,
last: number,
comp: (a: number, b: number) => boolean,
): void;
export function select<T>(
array: T[],
first: number,
nth: number,
last: number,
comp: (a: T, b: T) => boolean,
): void;
export function select<T>(
array: Float32Array | T[],
first: number,
nth: number,
last: number,
comp: (a: number | T, b: number | T) => boolean,
): void;
export function select<T>(
array: Float32Array | T[],
first: number,
nth: number,
last: number,
comp: (a: number | T, b: number | T) => boolean,
): void {
// Implementation of Floyd-Rivest algorithm
// Some code
let newFirst = 0
let newLast = 0
select(array, newFirst, nth, newLast, comp);
// Some code
}
导出功能选择(
数组:Float32Array,
第一:数字,
N:号码,
最后:号码,,
comp:(a:number,b:number)=>布尔值,
):无效;
导出功能选择(
数组:T[],
第一:数字,
N:号码,
最后:号码,,
comp:(a:T,b:T)=>布尔值,
):无效;
导出功能选择(
数组:Float32Array | T[],
第一:数字,
N:号码,
最后:号码,,
comp:(a:number | T,b:number | T)=>布尔值,
):无效;
导出功能选择(
数组:Float32Array | T[],
第一:数字,
N:号码,
最后:号码,,
comp:(a:number | T,b:number | T)=>布尔值,
):无效{
//Floyd-Rivest算法的实现
//一些代码
设newFirst=0
设newLast=0
选择(数组、新第一个、第n个、新最后一个、复合);
//一些代码
}
另一种解决方案是使用更通用的类型,并适用于这两种类型的数组,如注释中所建议。如果将T[]
更改为ArrayLike
,该怎么办?由于还允许使用Float32Array
,因此将不会使用任何数组原型函数。如果您也在for of循环中使用它,或者您可以添加ArrayLike&Iterable
。谢谢,我不知道Typescript中的这些类型。Iterable似乎可以工作(因此不需要重载)。我不能使用ArrayLike,它看起来是只读的(数组在实现中是可变的)。添加联合签名基本上不符合重载的目的吗?不一定。。对于floatarray
,第一个重载将处于活动状态,因此回调将使用数字。对于其他T[]
s,回调将采用T
。只有当它是一个类型为FloatArray | T[]
的并集时,才会触发最后一个重载。但是,似乎您基本上可以传递满足该并集的任何内容,并编译它,即使它可能是一个错误。。。像select(floatArray,1,2,3,(a:string,b:string)=>a==b)
是允许的,因为它floatArray
匹配Float32Array
和(string,string)=>boolean
匹配(T,T)=>boolean
。。。即使它不再有意义。