You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript:元组作为剩余参数报错的原因与解决问询

问题:TypeScript中如何让编译器识别元组作为剩余参数的数组类型?

我定义了一个用于判断类型是固定长度元组还是数组的类型,想借此推断函数参数类型。实际调用时,参数one、two、arr都能正确推断,但在? (...params: T[K]) => void处报错:A rest parameter must be of an array type。明明元组属于数组类型,请问怎么引导编译器正确识别?

代码示例

type ANumber = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;

type IsTuple<Type> = Type extends readonly unknown[] ? Type['length'] extends ANumber ? true : false : false;

function fn<T extends Record<keyof T, unknown>>() {
  return function withConfig(config: {
    [K in keyof T]: IsTuple<T[K]> extends true
      ? (...params: T[K]) => void
      : (param: T[K]) => void
  }) {};
}

fn<{ tupleType: [number, number], arrayType: number[] }>()({
  tupleType: (one, two) => {},
  arrayType: (arr) => {}
})

报错信息

A rest parameter must be of an array type


解决方案

问题核心在于:仅通过IsTuple<T[K]> extends true的条件判断,TypeScript无法反向推导出T[K]一定是数组/元组类型,因此会认为剩余参数的类型不符合要求。我们需要先明确约束T[K]为数组类型,再区分元组和数组:

修改后的代码

type ANumber = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;

type IsTuple<Type> = Type extends readonly unknown[] ? Type['length'] extends ANumber ? true : false : false;

function fn<T extends Record<keyof T, unknown>>() {
  return function withConfig(config: {
    [K in keyof T]: T[K] extends readonly unknown[] 
      ? IsTuple<T[K]> extends true
        ? (...params: T[K]) => void
        : (param: T[K]) => void
      : (param: T[K]) => void
  }) {};
}

fn<{ tupleType: [number, number], arrayType: number[] }>()({
  tupleType: (one, two) => {},
  arrayType: (arr) => {}
})

更简洁的写法

直接利用元组length为字面量类型、数组length为number类型的特性合并判断:

function fn<T extends Record<keyof T, unknown>>() {
  return function withConfig(config: {
    [K in keyof T]: T[K] extends readonly unknown[]
      ? T[K]['length'] extends number & ANumber
        ? (...params: T[K]) => void
        : (param: T[K]) => void
      : (param: T[K]) => void
  }) {};
}

原理说明

先通过T[K] extends readonly unknown[]明确告诉编译器:当前分支下的T[K]是数组类型(包括元组),此时剩余参数...params: T[K]的类型就会被正确识别。后续再通过IsTuple或length的特性区分元组和数组,生成对应的函数签名。


内容的提问来源于stack exchange,提问作者Andy Jessop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 14:51:04