Typescript 使用类作为模板还是参数?
假设我想要一个类dict,这样我就可以管理本地唯一的类(每个类dict实例) 我试图实现以下内容,但似乎是多余的:Typescript 使用类作为模板还是参数?,typescript,Typescript,假设我想要一个类dict,这样我就可以管理本地唯一的类(每个类dict实例) 我试图实现以下内容,但似乎是多余的: // 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]
// 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;
}
我怎样才能做到这一点?提前感谢。我们将
A级
作为new()=>A级
。所以你必须给出get(t:new()=>t)
下面是如何在typescript中完全完成的:
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)
当使用
--lib
时,您必须指定typescript应该使用的所有库,包括默认库,此处需要明确提及它隐式使用的库。我更改了API,该API只支持构造函数。(update
和remove
被省略,因为它们是相同的)
type ComponentConstructor=new(e:IEntity)=>C;
类实体实现了可扩展性{
受保护的_组件:{[k:string]:IComponent};
公共AddComponent(ctor:ComponentConstructor):C{
常数k=(如有)。名称;
如果(此._组件[k]==未定义){
常数c=新的系数(本);
这是._分量[k]=c;
}否则{
console.warn(k+'已存在');
}
将此返回。_组件[k]作为C;
}
公共GetComponent(ctor:ComponentConstructor):C{
常数k=(如有)。名称;
将此返回。_组件[k]作为C;
}
}
//用户案例
类MyE扩展了ecs.Entity{}
类MyC扩展了ecs.Component{}
常数e=新的MyE();
常数c=e.AddComponent(MyC);
e、 GetComponent(MyC);
t.name的本意是什么?它没有在代码中的任何地方定义shown@MoreThanTom它是内置字段。每个构造函数都可以调用它来获取类的名称。您可以在控制台classa{}中尝试;A.name
。在我的示例中,它将返回'A'
语义错误TS2339属性'name'在类型'new()=>T'
上不存在,您在哪一行得到此错误?您使用的ts版本是什么。上面共享的操场链接中似乎没有错误。get
的实现您正在使用哪个版本的ts?你检查过上面的链接了吗?似乎没有错误。typescript
是3.1.2
。我正在使用vscode
和npm
。我使用了tsc
进行编译并得到了错误。在typescript
中不建议使用any
。你只是绕过了它。而是直接使用javascript。
// 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>()
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)
tsc test.ts --lib 'dom','es2018'
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);