假设我想要一个类字典,这样我就可以管理局部唯一的类(每个类字典实例)。
class A { }
class ClassDict {
kvp: { [k:string]: any }; // not sure if there is better way
}
b = new ClassDict()
我尝试实现以下方法,但这似乎是多余的:
// call as b.add<A>(new A())
public add<T>(t: T): T {
this.kvp[t.name] = t;
return t;
}
// call as b.get<A>(A)
public get<T>(t: any): T {
return this.kvp[t.name] as any as T;
}
如果仅在模板中使用类,则无法调用.name
来获取密钥。
如果仅使用class作为参数,则无法声明返回类型。
我希望我可以这样打电话:
// creates an object of A
// since param is instance of A, it is supposed to know it
b.add(new A())
// updates an object of A
// same as add
b.update(new A())
// returns an object of A
b.get(A);
// or
b.get<A>()
// removes an object of A, this might be easier as it returns void
b.remove(A)
// or
b.remove<A>()
我该如何实现?预先感谢。
答案 0 :(得分:1)
我们将class A
作为new()=>A
。所以你必须给get<T>(t: new()=>T)
这是它在打字稿中的完成方式:
class A {
}
class ClassDict {
kvp: { [k: string]: any } = {};
public add<T>(t: T){
this.kvp[t.constructor.name] = t;
}
public get<T>(t: new()=>T) {
return this.kvp[t.name] as T;
}
public update<T>(t:T) {
this.kvp[t.constructor.name] = t;
}
public remove<T>(t: new()=>T) {
this.kvp[t.name] = undefined;
}
}
let b = new ClassDict()
b.add<A>(new A())
let d = b.get(A); // typeof d is A
b.update(new A())
b.remove(A)
您可以在Typescript Playground here看到实时工作。发表评论,以备不时之需。
更新:
ES6附带了函数的.name
属性。因此,为了使打字稿知道这一点,您必须在配置中包括最新的库:
tsc test.ts --lib 'dom','es2018'
使用--lib
时,您必须指定打字稿应使用的所有库,包括隐式使用的默认库,此处需要明确提及。
答案 1 :(得分:0)
我更改了add
仅支持构造函数的API。 ({update
和remove
被省略,因为它们相同)
type ComponentConstructor<C extends IComponent> = new (e: IEntity) => C;
class Entity implements IEntity {
protected _components: { [k: string]: IComponent };
public AddComponent<C extends IComponent>(ctor: ComponentConstructor<C>): C {
const k = (ctor as any).name;
if (this._components[k] === undefined) {
const c = new ctor(this);
this._components[k] = c;
} else {
console.warn(k + ' already exists.');
}
return this._components[k] as C;
}
public GetComponent<C extends IComponent>(ctor: ComponentConstructor<C>): C {
const k = (ctor as any).name;
return this._components[k] as C;
}
}
// user case
class MyE extends ecs.Entity { }
class MyC extends ecs.Component { }
const e = new MyE();
const c = e.AddComponent(MyC);
e.GetComponent(MyC);