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

如何为动态定义的Drawer类修改函数参数对象并通过TypeScript校验?

解决方案

核心类型工具

先定义两个通用类型工具,用来转换函数的参数类型:

// 移除对象类型中的ctx属性
type OmitCtx<T> = Omit<T, 'ctx'>;

// 将目标函数的参数对象中移除ctx属性,生成新的函数类型
type TransformFunc<F> = F extends (args: infer Args) => infer R 
  ? Args extends object 
    ? (args: OmitCtx<Args>) => R 
    : F // 兼容非对象参数场景(当前需求可忽略)
  : never;

// 批量转换draw对象的所有方法类型,生成Drawer需要的方法集合
type DrawerMethods<T> = {
  [K in keyof T]: TransformFunc<T[K]>;
};

完整实现代码

结合动态添加方法的逻辑,完整的TypeScript实现如下:

// 定义ctx的具体类型(以Canvas 2D上下文为例)
type CanvasCtx = CanvasRenderingContext2D;

// 原始draw对象及类型定义
const draw = {
  pixel({ ctx, x, y }: { ctx: CanvasCtx; x: number; y: number }): void {
    ctx.fillRect(x, y, 1, 1);
  },
  line({ ctx, startX, startY, endX, endY }: { ctx: CanvasCtx; startX: number; startY: number; endX: number; endY: number }): void {
    ctx.beginPath();
    ctx.moveTo(startX, startY);
    ctx.lineTo(endX, endY);
    ctx.stroke();
  }
  // 更多绘制方法...
} as const;

// 生成Drawer的完整实例类型
type DrawerInstance = Drawer & DrawerMethods<typeof draw>;

// 定义Drawer基础类
class Drawer {
  ctx: CanvasCtx;

  constructor(ctx: CanvasCtx) {
    this.ctx = ctx;
  }
}

// 动态为Drawer原型添加所有draw方法
Object.keys(draw).forEach(key => {
  const methodKey = key as keyof typeof draw;
  Drawer.prototype[methodKey] = function (args = {}) {
    return draw[methodKey]({ ctx: this.ctx, ...args });
  };
});

// 创建实例并断言类型,获得完整类型提示
const canvas = document.getElementById('canvas') as HTMLCanvasElement;
const ctx = canvas.getContext('2d') as CanvasCtx;
const drawer = new Drawer(ctx) as DrawerInstance;

// 调用时无需传入ctx,TypeScript自动校验参数
drawer.pixel({ x: 10, y: 10 });
drawer.line({ startX: 0, startY: 0, endX: 100, endY: 100 });

无断言替代方案

如果不想使用类型断言,可以通过接口合并让TypeScript自动识别Drawer的方法:

// 生成Drawer的方法类型
type DrawerMethodsType = DrawerMethods<typeof draw>;

// 扩展Drawer接口,注入动态方法的类型
interface Drawer extends DrawerMethodsType {}

// 后续Drawer类定义、动态添加方法逻辑不变
// 创建实例时直接使用,无需断言
const drawer = new Drawer(ctx);

该方案利用TypeScript的条件类型推断和映射类型,自动复用原始draw对象的类型定义,既避免了重复代码,又让动态添加的方法获得完整的类型校验与提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:50:28