TypeScript运行时如何区分函数与类构造函数?
运行时区分Error构造函数与工厂函数的方法
在TypeScript编译后的JavaScript环境中,typeof对类构造函数和普通函数的返回结果都是function,无法直接区分。可以通过以下几种可靠的方式判断参数是类构造函数还是返回Error的工厂函数:
方法1:检查函数的toString输出
类构造函数(包括ES6类)的toString()结果通常以class 开头,而普通函数的结果以function 开头。这种方法简单直接,适用于未被代码压缩混淆的场景:
function doSomething(errorFactory: typeof Error | (() => Error)) { if (errorFactory.toString().startsWith('class ')) { // errorFactory is a class constructor const err = new errorFactory('message'); } else { // errorFactory is a factory function const err = errorFactory(); } }
方法2:通过原型链检测
类构造函数的prototype属性上会包含其类的原型特征(比如自定义Error类的prototype会继承自Error.prototype)。可以通过判断prototype是否具备Error实例的特征来区分:
function doSomething(errorFactory: typeof Error | (() => Error)) { if (typeof errorFactory.prototype === 'object' && errorFactory.prototype instanceof Error) { // errorFactory is a class constructor const err = new errorFactory('message'); } else { // errorFactory is a factory function const err = errorFactory(); } }
注:如果自定义Error类正确继承了Error,其prototype会是Error的实例,这个判断会生效。
方法3:尝试实例化并验证类型
通过尝试用new调用参数,判断返回结果是否为Error实例;同时处理工厂函数被new调用的场景,这种方法兼容性最好,即使代码被压缩也能正常工作:
function doSomething(errorFactory: typeof Error | (() => Error)) { let err: Error; try { // 先尝试当作构造函数调用 err = new errorFactory('test'); if (err instanceof Error) { // 确认是类构造函数 } else { // 构造调用返回非Error,转为工厂函数调用 err = errorFactory(); } } catch (e) { // 构造调用失败,当作工厂函数处理 err = errorFactory(); } }
内容的提问来源于stack exchange,提问作者noamtm
相关产品推荐
相关产品推荐

