引言
一般情况下,在typescript中如果我们要为某个第三方库的类扩展类成员,可以采用如下方法:
// thirdLib.ts
class ModuleBase{
}
// myapp.ts
declare module "thirdLib" {
interface ModuleBase {
count():number
}
}
只需要在工程中使用interface就可以为类扩展成员类型。
最近在为一个monorepo多包工程下使用typescript扩展类成员,遇到一个坑无法扩展类,至今也不知道是什么原因,读者如有知道的,请留言指点!
问题描述
typescript版本5.1.6- 包管理工具采用
pnpm - 项目是一个
monorepo工程,结构如下
myapp
|--packages
|-- core // 包名:@voerka/core
|--src
|-- module.ts // 里面导出class ModuleBase
|-- index.ts
|-- app // 包名:@voerka/app
|-- nodejs // 包名:@voerka/nodejs
|-- exchange // 包名:@voerka/exchange
|--src
|--types.ts
|--index.ts // export * from "./types"
|--examples
|--testapp
index.ts
- 以上
app、nodejs、exchange均安装@voerka/core为peerDependencies examples/testapp依赖于@voerka/core和@voerka/nodejs,@voerka/nodejs依赖于@voerka/appexamples/testapp依赖@voerka/exchange- 然后在
@voerka/exchange包的types.ts中,扩展了@voerka/core中的Class ModuleBase,如下:
declare module "@voerka/core" {
interface ModuleBase {
count():number
}
}
// 此处我们只讨论扩展类型,不考虑实现。
examples/testapp/index.ts内容如下:
import {ModuleBase} from "@voerka/core
class MyModule extends ModuleBase{
}
正常情况下,以下代码应该能够正常工作,我们通过interface ModuleBase 扩展了存在于@voerka/core
在examples/testapp/index.ts中的MyModule应该是继承了@voerka/core中的ModuleBase,并且具有一个count成员方法。
问题:
而我的项目中,以上扩展ModuleBase方法并不能生效,而是直接就提示无法扩展接口‘ModuleBase’。您的意思是‘实施’吗?ts(2689)错误。
我发现,在@voerka/exchange包的types.ts中declare module "@voerka/core"的interface ModuleBase覆盖了@voerka/core中的类声明,是覆盖类型定义,而不是合并,导致了ModuleBase从一个类变成了一个interface,从而无法进行类继承。
问题解决
为了解决此问题,我做了很多尝试:
- 向
chatGPT,百度文心一言等均无法给出解决方案,或许是我问的方法有问题,或许是问题太复杂,没有得到有效的答案。 - 生新构建了一个
monorepo工程,但是却无法复现。 - 一度怀疑是否
class无法通过interface扩展。
最终无意中的一个举动解决了此问题,在声明模块时将@voerka/core 更改为@voerka//core
declare module "@voerka//core" {
interface ModuleBase {
count():number
}
}
小结
- 当扩展模块名称是
@xxxx/xxx形式时,可以将之声明@xxxx//xxx形式 - 只所以说是诡异是因为,我完全重建一个
monorepo工程,但是却无法复现。 - 没找到官方或者哪里的文档说明这个小细节。