如何在 TypeScript 中扩展未导出的 class?
How to extend a non-exported class in TypeScript?
在我的 TypeScript 程序中,我想扩展在库中声明的 class。诀窍是该库不会“导出”它,所以我无法直接访问它。相反,它提供了一个构建器函数,如下所示:
export namespace Library {
class BaseUnexported { // no export here, for some reason
public foo() { console.log("foo"); }
}
export function buildUnexportedInstance(): BaseUnexported {
return new BaseUnexported();
}
}
我正在尝试像这样扩展 class:
import { Library } from "./library";
export default class Derived extends Library.BaseUnexported {
public bar() { console.log("bar"); }
}
如果库“导出”了 class 定义,这将起作用;但是没有出口我得到 error TS2339: 属性 'BaseUnexported' does not exist on type 'typeof Library'.
我试图从构造函数中获取类型,例如:
type BaseType = ReturnType<typeof Library.buildUnexportedInstance>
export default class Derived extends BaseType {
而这一次得到错误TS2693:'BaseType'只引用了一个类型,但在这里被用作一个值。
所以,我的问题是:有没有办法扩展没有“export”关键字声明的 class?也许是一些基于原型的魔法?
请注意,我的目标是创建一个新的class,我想保持原来的class不变。
P.S。这是一个简化的例子;事实上,我正在尝试从一个名为 blessed 的很棒的库中扩展小部件。只想创建我自己的小部件,以扩展现有小部件的功能。
简单的回答,你不能做你想做的事。看起来工厂的存在纯粹是为了阻止你扩展基础 class。在我看来,这是一件合理的事情,因为它肯定会阻止由您自己的代码创建的错误,这些错误会出现在基础 class.
中
您有一些选择,我最不推荐的是分叉项目并将 class 公开给扩展。这在我看来是不可取的,因为您会敞开心扉接受可能很乏味的手动更新,并且它会让您有动力开始搞乱封闭的(并且可能经过严格测试的)代码。
相反,我希望将组合而不是扩展作为一种可行的(并且可能更好)替代方案,例如装饰基础 class 或使用您自己的 builder/director 创建使用实例的小部件基础class 但在顶部有您自己的功能。
您不能做的是修改基本实例方法或非 public 内部结构,这可能是也可能不是您的症结所在。
我不知道你正在使用的库,这可能是不可能的(毕竟),这取决于不同库方法的输出是什么,但是,例如我可能会尝试:
// As the type doesn't exist in scope you could expose
// it yourself with a custom `.d.ts`.
class MyWidgetLibrary implements BaseLibrary {
private library: BaseLibrary;
constructor(library: BaseLibrary) {
this.library = library;
}
// for example create decorator methods to wrap the base widgets
}
在我的 TypeScript 程序中,我想扩展在库中声明的 class。诀窍是该库不会“导出”它,所以我无法直接访问它。相反,它提供了一个构建器函数,如下所示:
export namespace Library {
class BaseUnexported { // no export here, for some reason
public foo() { console.log("foo"); }
}
export function buildUnexportedInstance(): BaseUnexported {
return new BaseUnexported();
}
}
我正在尝试像这样扩展 class:
import { Library } from "./library";
export default class Derived extends Library.BaseUnexported {
public bar() { console.log("bar"); }
}
如果库“导出”了 class 定义,这将起作用;但是没有出口我得到 error TS2339: 属性 'BaseUnexported' does not exist on type 'typeof Library'.
我试图从构造函数中获取类型,例如:
type BaseType = ReturnType<typeof Library.buildUnexportedInstance>
export default class Derived extends BaseType {
而这一次得到错误TS2693:'BaseType'只引用了一个类型,但在这里被用作一个值。
所以,我的问题是:有没有办法扩展没有“export”关键字声明的 class?也许是一些基于原型的魔法? 请注意,我的目标是创建一个新的class,我想保持原来的class不变。
P.S。这是一个简化的例子;事实上,我正在尝试从一个名为 blessed 的很棒的库中扩展小部件。只想创建我自己的小部件,以扩展现有小部件的功能。
简单的回答,你不能做你想做的事。看起来工厂的存在纯粹是为了阻止你扩展基础 class。在我看来,这是一件合理的事情,因为它肯定会阻止由您自己的代码创建的错误,这些错误会出现在基础 class.
中您有一些选择,我最不推荐的是分叉项目并将 class 公开给扩展。这在我看来是不可取的,因为您会敞开心扉接受可能很乏味的手动更新,并且它会让您有动力开始搞乱封闭的(并且可能经过严格测试的)代码。
相反,我希望将组合而不是扩展作为一种可行的(并且可能更好)替代方案,例如装饰基础 class 或使用您自己的 builder/director 创建使用实例的小部件基础class 但在顶部有您自己的功能。
您不能做的是修改基本实例方法或非 public 内部结构,这可能是也可能不是您的症结所在。
我不知道你正在使用的库,这可能是不可能的(毕竟),这取决于不同库方法的输出是什么,但是,例如我可能会尝试:
// As the type doesn't exist in scope you could expose
// it yourself with a custom `.d.ts`.
class MyWidgetLibrary implements BaseLibrary {
private library: BaseLibrary;
constructor(library: BaseLibrary) {
this.library = library;
}
// for example create decorator methods to wrap the base widgets
}