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

TypeScript实现可插拔函数时如何推断新增方法的类型?

实现可插拔函数的类型推断方案

你当前写法无法正确推断新增方法类型的核心原因是:TypeScript的断言函数只能对**函数自身的参数或this**做类型断言,无法直接修改闭包捕获变量的类型。我们可以通过调整断言目标为this,并提取精确的方法类型来解决这个问题。

完整实现代码

export function register<T>(o: T) {
  // 泛型K指定属性名,V从value中提取精确方法类型
  return <K extends PropertyKey, V extends Function>(
    this: T,
    p: K,
    attributes: PropertyDescriptor & { value: V } & ThisType<unknown>,
  ): asserts this is T & Record<K, V> => {
    Object.defineProperty(this, p, attributes);
  };
}

// 声明mylib的基础类型,包含register方法的类型定义
type Mylib = (() => void) & {
  register?: ReturnType<typeof register<() => void>>;
};

export const mylib = (() => {}) as Mylib;

// 挂载register方法
mylib.register = register(mylib);

// 注册teste方法,TypeScript将自动推断其类型
mylib.register('teste', {
  writable: false,
  value(a: number, b: number) {
    return a + b;
  },
});

console.info("a:", mylib.teste(1, 1)); // 类型推断正常,输出2
console.info("a:", mylib.teste('1', '1')); // 触发类型错误,符合预期

关键调整说明

  1. 断言this类型:
    调用mylib.register时,this会绑定到mylib本身。通过asserts this is T & Record<K, V>,我们直接扩展了this(即mylib)的类型,让TypeScript能识别新增的属性。

  2. 提取精确方法类型:
    新增泛型V,从attributes.value中提取具体的函数类型,替代原来宽泛的PropertyDescriptorValue,确保类型推断的精准度。

  3. 提前声明类型:
    通过type Mylib提前定义mylib的结构,确保register方法的类型被正确识别,避免TypeScript将其推断为any。

简化写法(无需提前声明类型)

如果不想提前定义类型,也可以在赋值register时用类型断言:

export const mylib = () => {};

// 赋值时指定register的类型
mylib.register = register(mylib) as typeof mylib['register'];

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 00:55:07