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

如何为带动态参数方法的动态对象添加TypeScript类型

如何为invokeActions方法添加TypeScript类型以校验参数错误

我实现了如下方法:

const invokeActions = (target, actions) => {
  actions.forEach(({ action, args }) => {
    target[action](...args);
  });
}

需要为该方法添加正确的TypeScript类型,让编译器能检测出调用函数时的参数数量错误、参数类型错误。使用示例如下:

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

const actions = [
  { action: 'moveTo', args: [0, 0] },
  { action: 'lineTo', args: [100, 100] },
  { action: 'closePath', args: ['error'] }, // 此处应该触发TypeScript编译错误
  { action: 'closePath', args: [1, 2] },    // 同样应该触发错误
];

invokeActions(ctx, actions);

我曾尝试用interface定义类型,但closePath被错误地允许传入[]和[number, number],不符合预期:

interface Drawable {
  moveTo: (x: number, y: number) => void;
  lineTo: (x: number, y: number) => void;
  closePath: () => void;
}

type ActionType = {
  action: Drawable[keyof Drawable] extends (...args: any[]) => void ? keyof Drawable : never;
  args: Drawable[keyof Drawable] extends (...args: any[]) => void ? Drawable[keyof Drawable] : never;
}

我还尝试过结合infer、Parameters<T[keyof T]>等方式,但都没能解决问题。


解决方案

要实现严格的参数校验,需要让每个Action的args类型与对应action方法的参数类型严格匹配,这里可以用映射类型结合联合类型来实现:

// 定义通用的Action类型,针对目标对象T的每个方法生成对应的动作类型
type Action<T> = {
  [K in keyof T]: T[K] extends (...args: infer Args) => void 
    ? { action: K; args: Args } 
    : never
}[keyof T];

// 为invokeActions添加泛型类型
const invokeActions = <T extends Record<string, (...args: any[]) => void>>(
  target: T,
  actions: Action<T>[]
) => {
  actions.forEach(({ action, args }) => {
    target[action](...args);
  });
};

类型说明:

  • Action<T>类型:

    • 遍历目标对象T的所有键K,判断T[K]是否是函数
    • 如果是函数,用infer Args提取出该函数的参数类型,生成{ action: K; args: Args }的类型
    • 最后通过[keyof T]将映射类型转为联合类型,这样每个动作都会严格对应自己的参数类型
  • invokeActions的泛型定义:

    • 用T extends Record<string, (...args: any[]) => void>约束目标对象必须是包含函数属性的对象
    • actions参数指定为Action<T>[],这样数组中的每个元素都必须是符合对应方法参数要求的动作对象

效果验证:

在示例中:

  • { action: 'closePath', args: ['error'] }会触发错误,因为closePath的参数类型是[],传入['error']不匹配
  • { action: 'closePath', args: [1, 2] }同样会触发错误,参数数量不匹配
  • 而moveTo和lineTo传入正确的[number, number]参数则不会有问题

该类型定义也能自动适配可选参数、剩余参数的场景,因为infer Args会完整提取函数的参数类型信息。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 11:27:09