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

如何在TypeScript中返回保留接口的类并实现可调用?

解决方案

1. 核心思路:复用变量名+类型别名

通过TypeScript的InstanceType工具类型,我们可以直接从构造函数值中提取实例类型,无需额外的下划线命名或重复定义类结构。同时优化wrap函数的类型定义,确保运行时和类型检查都正常工作。

完整实现代码

// 实现wrap函数:运行时用Proxy让构造函数可直接调用,类型上保留原构造函数类型
function wrap<T extends new (...args: any[]) => any>(ctor: T): T {
  return new Proxy(ctor, {
    apply(target, _, args) {
      return new target(...args);
    }
  }) as T;
}

// 定义类并包装,同时创建同名类型别名指向实例类型
const Foo = wrap(class {
  x: number;
  y: number;
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
});
type Foo = InstanceType<typeof Foo>;

// 两种调用方式均正常,类型检查通过
const foo1: Foo = new Foo(1, 2);
const foo2: Foo = Foo(3, 4);

方案优势

  • 无需_Foo这类不美观的命名,类表达式可直接匿名定义
  • 类直接在wrap函数内部定义,无需提前暴露到外部上下文
  • 仅需两次Foo命名(变量名和类型别名),大幅减少重复

2. 支持类内部自引用的写法

如果需要在类内部使用自身类型,可以给类表达式添加内部名称,同时类型别名依然复用外部变量名:

function wrap<T extends new (...args: any[]) => any>(ctor: T): T {
  return new Proxy(ctor, {
    apply(target, _, args) {
      return new target(...args);
    }
  }) as T;
}

const Foo = wrap(class Foo {
  x: number;
  y: number;
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
  // 类内部可直接用Foo作为实例类型
  clone(): Foo {
    return new Foo(this.x, this.y);
  }
});
type Foo = InstanceType<typeof Foo>;

const foo: Foo = Foo(1, 2);
console.log(foo.clone()); // 类型检查正常

3. 简化类型别名的通用技巧

如果觉得InstanceType<typeof Foo>写法冗余,可以定义一个通用类型别名复用:

type Instance<T> = T extends new (...args: any[]) => infer R ? R : never;

// 后续只需写:
type Foo = Instance<typeof Foo>;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 01:13:23