我正在用Typescript2.0编写一个库,这个库也可以从javascript中使用。
我有一个类Component和一个函数registerComponent,它是由打字本组成的。
我需要通过调用Component来存储继承registerComponent的类的构造函数。注册的组件可以由我的库自动实例化。在某些情况下,方法的参数可以不是函数而是对象。我需要将对象转换为生成传递对象的构造函数。
但是,该构造函数也应该扩展Component类。所以,我的意思是,我想把一个类作为超类注入到一个函数中,这个函数会用类型记录生成给定的对象。
这是在registerComponent中处理原始对象的部分。
const newCtor = function() {
Component.call(this);
};
const properties = {};
for (let key in obj) {
properties[key] = { value: obj[key] };
}
newCtor.prototype = Object.create(Component.prototype, properties);
return newCtor;obj由用户提供普通对象。我认为这段代码可以工作,但实际上,当我使用带有新关键字的构造函数时,这段代码会填充一个错误的Uncaught TypeError: Class constructor Component cannot be invoked without 'new'。该异常将抛出在代码Component.call(this)上。
如何使用注入超类创建有效的构造函数?
我很抱歉在如此模棱两可的帖子中问。但是现在我认为我需要发布我想要实现的完整界面。
class Component{
public baseFunction():string
{
return "This is base";
}
}
class Registory{
private static registeredConstructors:{[key:string]:(new()=>Component)};
public static registerComponent(name:string,c:(new()=>Component)|{[key:string]:any}):void
{
if(typeof c === "function")
{
Registory.registeredConstructors[name] = c;
return;
}else{
// Assume c is plain object
// I need some code here to wrap c as constructor
}
}
public static instanciate(name:string):Component
{
return new Registory.registeredContructors[name]();
}
}
// When User want to register component via Typescript class
class C1 extends Component{
public someProperty:string = "HELLO C1";
public f1():string{
return this.baseFunction() + this.someProperty;
}
}
Registory.registerComponent("C1",C1);
const c1:Component = Registory.instanciate("C1");
// When user want to register component via plain object
Registory.registerComponent("C2",{
someProperty:"Hello C2",
f1:function(){
return this.baseFunction() + this.someProperty;
}
});
const c2:Component = Registory.instanciate("C2");
// This is the test c1 and c2 should pass
test.true(()=>c1 instanceof Component);
test.true(()=>c2 instanceof Component);
test.true(()=>c1.f1() === "This is base Hello C1");
test.true(()=>c2.f1() === "This is base Hello C2");
test.true(()=>c1 instanceof C1);发布于 2016-10-30 15:34:48
在我看来,如果我正确理解你的话,你的情况就可以更容易解决:
abstract class Component {
constructor(props: any) {}
}
type ComponentConstructor = {
new (props: any): Component;
name: string;
};
const REGISTRY = {} as { [name: string]: ComponentConstructor };
function registerComponent(ctor: ComponentConstructor) {
REGISTRY[ctor.name] = ctor;
}
function instantiateComponent(name: string, props: any): Component;
function instantiateComponent<T extends Component>(name: string, props: any): T {
if (typeof REGISTRY[name] !== "function") {
return null;
}
return new REGISTRY[name](props) as T;
}
class MyComponent1 extends Component { }
registerComponent(MyComponent1);
class MyComponent2 extends Component { }
registerComponent(MyComponent2);
let comp1 = instantiateComponent("MyComponent1", {}); // typeof comp1 is Component
let comp2: MyComponent2 = instantiateComponent("MyComponent2", {}); // typeof comp2 is MyComponent2(操场密码
编辑
好吧,既然我明白你想要什么,就更容易帮忙了。
我仍然需要清理您的代码,但是下面是您想要的:
interface IComponent {
someProperty: string;
f1(): string;
}
abstract class Component implements IComponent {
abstract someProperty: string;
abstract f1(): string;
public baseFunction(): string {
return "This is base ";
}
}
type ComponentConstructor = { new (): Component };
abstract class ComponentFromObject extends Component {
constructor(obj: IComponent) {
super();
Object.assign(this, obj);
}
}
class Registory {
private static registeredConstructors: { [key: string]: ComponentConstructor } = {};
public static registerComponent(name: string, c: ComponentConstructor | IComponent): void {
if (typeof c === "function") {
Registory.registeredConstructors[name] = c;
} else {
Registory.registeredConstructors[name] = ComponentFromObject.bind(null, c);
}
}
public static instanciate(name: string): Component {
return new Registory.registeredConstructors[name]();
}
}
const registory = new Registory();
// When User want to register component via Typescript class
class C1 extends Component {
public someProperty: string = "Hello C1";
public f1(): string {
return this.baseFunction() + this.someProperty;
}
}
Registory.registerComponent("C1", C1);
const c1: Component = Registory.instanciate("C1");
// When user want to register component via plain object
Registory.registerComponent("C2", {
someProperty: "Hello C2",
f1: function(){
return this.baseFunction() + this.someProperty;
}
});
const c2: Component = Registory.instanciate("C2");
// This is the test c1 and c2 should pass
console.log(c1 instanceof Component);
console.log(c2 instanceof Component);
console.log(c1.f1() === "This is base Hello C1");
console.log(c2.f1() === "This is base Hello C2");
console.log(c1 instanceof C1);(操场密码
https://stackoverflow.com/questions/40330446
复制相似问题