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

TypeScript中如何为多类型函数的参数数组实现精准类型校验?

问题

需要存储多个仅含单个参数的不同函数及其对应的参数值。目前仅能实现单一类型函数的类型校验,希望能同时传入多种类型函数,并为每个函数的参数提供正确的类型校验。

现有代码示例:

type WalkOptions = {
    x: number
    speed: number
}

type JumpOptions = {
    y: number
    speed: number
}

type ShootOptions = {
    type: string
    duration: number
}

const walk = (options: WalkOptions)=>{}
const jump = (options: JumpOptions)=>{}
const shoot = (options: ShootOptions)=>{}

type Action<T extends (options: any) => void> = {
    command: T
    args: Parameters<T>[0]
}

function add<T extends (options: any) => void>(...actions: Action<T>[]){}

当前调用add({command: walk, args:{x: 10, speed: 1}})或传入多个同类型函数时可正常校验,但传入不同类型函数(如同时传入walk和jump)会触发类型错误。

请问如何修改实现,使add函数支持传入多种类型函数,同时保证每个Action的args与对应command的参数类型匹配?另外,能否创建带类型校验的Action数组,用于add(...actionArray)的调用?


解决方案

1. 修改add函数以支持多类型Action

原代码中add函数的泛型T强制所有传入的Action必须是同一种函数类型,这是混合类型报错的核心原因。我们需要让add接受任意数量的不同类型Action,同时保留每个Action内部command和args的类型关联。

修改后的完整代码:

type WalkOptions = {
    x: number
    speed: number
}

type JumpOptions = {
    y: number
    speed: number
}

type ShootOptions = {
    type: string
    duration: number
}

const walk = (options: WalkOptions)=>{}
const jump = (options: JumpOptions)=>{}
const shoot = (options: ShootOptions)=>{}

// 保留Action的类型关联:command的参数类型决定args的类型
type Action<F extends (args: any) => void> = {
    command: F
    args: Parameters<F>[0]
}

// 修改add函数,允许传入任意多个不同类型的Action实例
function add(...actions: Array<Action<any>>){}

此时调用add传入混合类型函数会自动校验每个Action的args是否匹配对应command的参数类型:

// 正确调用:每个args都匹配对应command的参数
add(
    {command: walk, args:{x: 10, speed: 1}},
    {command: jump, args:{y: 20, speed: 2}},
    {command: shoot, args:{type: "fire", duration: 5}}
);

// 错误调用:walk的args缺少x参数,TypeScript会触发类型报错
add({command: walk, args:{speed: 1}});

2. 创建带类型校验的Action数组

可以通过两种方式创建带类型校验的Action数组:

方式1:自动推导数组类型(推荐)

直接创建数组,TypeScript会自动推导每个元素的类型并完成校验:

const actionArray = [
    {command: walk, args:{x: 10, speed: 1}},
    {command: jump, args:{y: 20, speed: 2}},
    {command: shoot, args:{type: "fire", duration: 5}}
];

add(...actionArray); // 正常工作,数组内每个元素都会被类型校验

方式2:显式声明数组类型

如果需要更严格的类型约束,可以声明数组为具体Action类型的联合数组:

const actionArray: Array<Action<typeof walk> | Action<typeof jump> | Action<typeof shoot>> = [
    {command: walk, args:{x: 10, speed: 1}},
    {command: jump, args:{y: 20, speed: 2}},
    {command: shoot, args:{type: "fire", duration: 5}}
];

add(...actionArray);

也可以使用通用的Action数组类型:

type ActionArray = Array<Action<(args: any) => void>>;

const actionArray: ActionArray = [
    {command: walk, args:{x: 10, speed: 1}},
    {command: jump, args:{y: 20, speed: 2}}
];

无论哪种方式,数组内的元素都会被TypeScript校验,确保args与对应command的参数类型匹配。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 16:35:01