首页 > 解决方案 > 使用 Array 和 TypedArray 在 Typescript 中重载递归函数

问题描述

我有一个带有 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,
  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
}

arrayTypescript 在实现中递归调用select函数时抱怨变量:

'Float32Array | 类型的参数 T[]' 不可分配给类型为“(number | T)[]”的参数。

首先,我真的不明白为什么打字稿会尝试将参数类型与不同签名中不存在的类型进行array比较(number | T)[]。它是否尝试将函数的类型array与参数类型进行比较comp

当然我可以在实现签名中替换参数的类型arrayany它可以工作,但我想知道是否有更好的方法来处理这种情况。

标签: typescriptgenericsrecursionoverloading

解决方案


问题是实现重载(即最后一个)不能直接调用,因此当您递归调用函数时,类型必须与两个重载之一兼容,并且联合与任何一个都不兼容(打字稿将不要尝试组合签名以允许通过工会)

在这种情况下,最简单的解决方案是复制实现签名:

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
}

如评论中所建议的,另一种解决方案是使用更通用且适用于两种数组类型的类型。


推荐阅读