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

TypeScript中如何为带不同/额外参数的函数分配类型

TypeScript动态回调参数兼容方案

问题背景

需要实现通用函数evaluate_two,支持传入带不同额外参数的回调函数(如callback1/callback2/callback3),同时满足:

  • 无需硬编码联合类型,动态适配回调的参数结构
  • 调用时自动校验参数缺失(如evaluate_two(tesstobj, 'one', callback2)需提示缺少min参数)
  • 自动校验参数类型(如传入错误类型时提示不匹配)

当前实现出现类型不兼容错误:

Argument of type '(key: string, value: unknown, min: number, max?: number) => number' is not assignable to parameter of type '(key: string, val: unknown, ...args: unknown[]) => number'.
  Types of parameters 'min' and 'args' are incompatible.
    Type 'unknown' is not assignable to type 'number'.

解决方案

通过泛型提取回调的剩余参数类型,将回调函数的参数拆分为固定前两个参数(key和val)与动态剩余参数Args,并约束函数的可变参数必须匹配Args类型,实现完全动态的参数适配。

核心修改代码

const evaluate_two = <
    O extends Obj,
    Args extends unknown[],
    R
>(obj: O, prop: keyof O, vfunc: (key: string, val: unknown, ...args: Args) => R, ...args: Args) => {
    if (typeof prop !== 'string') throw new Error('error')
    return vfunc(prop, obj[prop], ...args)
}

完整验证代码

// callbacks
const callback1 = (key: string, value: unknown) => {
    if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
    return value
}

const callback2 = (key: string, value: unknown, min: number, max: number = Infinity) => {
    if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
    if (value < min || value > max) throw new Error('error')
    return value
}

const callback3 = (key: string, value: unknown, something: number) => {
    if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
    if (value === something) throw new Error('error')
    return value
}

type Obj = { [P: string]: unknown }

const tesstobj: Record<string, unknown> = { one: 1, two: 'two' }

// 原单参数回调函数
const evaluate = <
    O extends Obj,
    F extends (key: string, val: unknown) => ReturnType<F>
>(obj: O, prop: keyof O, vfunc: F) => {
    if (typeof prop !== 'string') throw new Error('error')
    return vfunc(prop, obj[prop])
}

// 改进后的多参数回调函数
const evaluate_two = <
    O extends Obj,
    Args extends unknown[],
    R
>(obj: O, prop: keyof O, vfunc: (key: string, val: unknown, ...args: Args) => R, ...args: Args) => {
    if (typeof prop !== 'string') throw new Error('error')
    return vfunc(prop, obj[prop], ...args)
}

// 原函数验证
evaluate(tesstobj, 'one', callback1) // 正常执行
evaluate(tesstobj, 'one', callback2) // 预期报错:回调参数不匹配

// 新函数验证
evaluate_two(tesstobj, 'one', callback2) // 提示缺少min参数
evaluate_two(tesstobj, 'one', callback2, 1)  // 正常执行(max为可选参数)
evaluate_two(tesstobj, 'one', callback2, 1, 10) // 正常执行

evaluate_two(tesstobj, 'one', callback3, 'wrong') // 提示类型不匹配:string不能赋值给number
evaluate_two(tesstobj, 'one', callback3, 1) // 正常执行

效果说明

  • 调用evaluate_two时,TypeScript会自动根据传入的回调函数推导所需额外参数,缺失时给出明确提示
  • 参数类型不匹配时,立即触发类型错误提示
  • 完全动态适配任意结构的回调函数,无需维护联合类型

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:05:17