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

TypeScript继承类混合声明组合在Jest中运行报错求助

问题原因分析

我之前也碰到过几乎一模一样的问题!这个报错大概率是Jest的转译/模块处理逻辑和TypeScript官方混入模式的实现不兼容导致的。

TypeScript官方的混入通常是通过动态生成子类、修改原型链的方式实现的,而Jest默认用Babel转译代码时,会把ES6类转译成ES5的构造函数形式。如果你的混入逻辑里存在直接调用类(比如Fairy()而不是new Fairy())的操作,转译后就会触发Cannot call a class as a function——因为ES5构造函数必须用new调用,但混入代码可能没处理好这一点。

至于为什么ts-node和Playground能正常运行?因为它们的执行环境更贴近原生TypeScript的处理逻辑,没有经过Babel那种深度转译,所以不会破坏混入的原型链和类调用逻辑。

解决办法

下面给你几个亲测有效的修复方案,按优先级排序:

1. 检查混入函数的实现,避免直接调用类构造函数

先看你的混入函数是不是类似官方示例的写法:

function SpriteMixin<T extends new (...args: any[]) => any>(Base: T) {
  return class extends Base {
    // 混入的属性和方法
  };
}

如果混入函数里有直接Base()的代码(没加new),那肯定会在Jest里报错。要确保所有类的实例化都通过new关键字,或者调整混入逻辑,让它只通过继承的方式扩展类,而不是直接调用构造函数。

2. 调整Jest的转译配置,适配TypeScript类

如果是Babel转译的锅,修改你的babel.config.js或者jest.config.js:

  • 确保@babel/preset-typescript和@babel/plugin-transform-classes的版本是最新的,后者能更好地处理类转译时的原型链问题。
  • 在jest.config.js里设置transformIgnorePatterns,别让Jest忽略你的类文件;如果项目用ES模块,开启useESM模式。

举个babel.config.js的配置例子:

module.exports = {
  presets: [
    ['@babel/preset-env', { targets: { node: 'current' } }],
    '@babel/preset-typescript'
  ],
  plugins: [
    '@babel/plugin-transform-classes'
  ]
};

3. 改用装饰器实现混入(兼容性更好)

如果你的项目允许用装饰器,这种方式在Jest里的兼容性会好很多。比如:

// 定义混入装饰器
function ApplyMixin(mixinClass: new () => any) {
  return function(target: Function) {
    Object.assign(target.prototype, mixinClass.prototype);
  };
}

// 使用装饰器
@ApplyMixin(YourMixinClass)
class Sprite extends Fairy {
  constructor() {
    super(); // 一定要显式调用父类构造函数
    // 你的初始化逻辑
  }
}

记得在tsconfig.json里开启装饰器支持:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

4. 显式处理中间类的构造函数

如果问题出在中间类Fairy身上,检查Sprite类有没有显式调用super()。Jest转译后,父类构造函数的调用逻辑可能会被混淆,显式调用super()能确保构造函数被正确初始化。

另外,要是混入函数需要传递参数给父类,一定要确保参数能正确传递到super()里。

验证小技巧

修改完之后,先在ts-node里跑一遍确认正常,然后在Jest里加个调试日志:

console.log(typeof Fairy);
console.log(Sprite.prototype instanceof Fairy);

如果打印出来typeof Fairy是function(正常,ES5转译后的类就是函数),但Sprite.prototype instanceof Fairy是false,那说明原型链被破坏了,得回头检查混入逻辑或者转译配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 23:32:59