Javascript 类型脚本:抽象泛型类的子类类型
我有一个基本泛型类:Javascript 类型脚本:抽象泛型类的子类类型,javascript,typescript,abstract-class,Javascript,Typescript,Abstract Class,我有一个基本泛型类: 抽象类基类{ 抽象项数组:数组; 静态getName():字符串{ 抛出新错误(`BaseClass-'getName'未被重写!`); } 内部逻辑(){} } 和继承人: 类型Item1={ 名称:string } 类Child1扩展了基类{ itemArray:Array=[]; 静态getName():字符串{ 返回“Child1”; } } 类型项2={ 姓名:号码 } 类Child2扩展了基类{ itemArray:Array=[]; 静态getName():
抽象类基类{
抽象项数组:数组;
静态getName():字符串{
抛出新错误(`BaseClass-'getName'未被重写!`);
}
内部逻辑(){}
}
和继承人:
类型Item1={
名称:string
}
类Child1扩展了基类{
itemArray:Array=[];
静态getName():字符串{
返回“Child1”;
}
}
类型项2={
姓名:号码
}
类Child2扩展了基类{
itemArray:Array=[];
静态getName():字符串{
返回“Child2”;
}
}
现在我想定义一个对象,其值为继承者:
类型IChildrenObj={
[键:字符串]:InstanceType;
};
/*
收到以下错误:类型“typeof BaseClass”不满足约束“new(…args:any)=>any”。
无法将抽象构造函数类型分配给非抽象构造函数类型。ts(2344)
*/
const childrenobj={
C1:Child1,
C2:Child2,
}
最后,我希望能够使用子对象的静态方法,并且能够创建它们的实例:
const-child:typeof-BaseClass=Children.C1;
/*
收到以下错误:类型“{getName:()=>string;}”中缺少属性“prototype”,但类型“typeof BaseClass”中需要属性“prototype”。ts(2741)
*/
log(child.getName());
const childInstance:BaseClass=new child();
/*
收到以下2个错误:
(1) 泛型类型“BaseClass”需要1个类型参数。ts(2314)
(2) 无法创建抽象类的实例。ts(2511)
泛型类型“BaseClass”需要1个类型参数。ts(2314)
*/
首先,类型
type IChildrenObj = {
[key: string]: InstanceType<typeof BaseClass>; // instances?
};
但这也不是儿童存储的内容:
const Children: IChildrenObj = {
C1: Child1, // error!
// Type 'typeof Child1' is not assignable to type 'typeof BaseClass'.
// Construct signature return types 'Child1' and 'BaseClass<T>' are incompatible.
C2: Child2, // error!
// Type 'typeof Child2' is not assignable to type 'typeof BaseClass'.
// Construct signature return types 'Child2' and 'BaseClass<T>' are incompatible.
}
类型subassofbaseclass
是of:一个生成基类的混凝土,它从typeof基类
中获取所有静态成员,而不同时获取有问题的抽象构造签名
让我们确保它工作正常:
const Children: IChildrenObj = {
C1: Child1,
C2: Child2,
} // okay
const nums = Object.values(Children)
.map(ctor => new ctor().itemArray.length); // number[]
console.log(nums); // [0, 0]
const names = Object.values(Children)
.map(ctor => ctor.getName()) // string[]
console.log(names); // ["Child1", "Child2"]
看起来不错
这里需要注意的是,虽然IChildrenObj
会起作用,但它的类型太模糊,无法跟踪您可能关心的事情,例如子类的特定键/值对,尤其是基类中的any
,以及any的奇怪的“随机应变”行为:
//索引签名假设每个键都存在:
试一试{
new Children.c4explorides()//可以编译,但是
}捕捉(错误){
console.log(错误);//请共享提供类/类型您希望值成为基类或类的实例吗?如果您希望类构造函数成为值,那么您就不希望InstanceType
。类型IChildrenObj
将不会以您希望的方式发挥作用;相反,您似乎只想将子类
约束为作为其中的子类构造函数,在这种情况下,您最好使用受约束的辅助函数,如。使用typeof BaseClass
(不合适)或childInstance
作为BaseClass
(无效类型)注释child1
也是如此.你能详细说明一下为什么需要这些类型吗?为什么不在链接代码中使用类型推断呢?也许这篇文章对你会有帮助@A-S我想@captain yossarian写了那篇文章,但其中有一些代码是我写的。总之,对你有用吗?基本上基类你可以做得更好,但现在我想说只需使用基类
并继续。如果可行,我可以写一个答案。如果不行,请告诉我还有什么问题。
type SubclassOfBaseClass =
(new () => BaseClass<any>) & // a concrete constructor of BaseClass<any>
{ [K in keyof typeof BaseClass]: typeof BaseClass[K] } // the statics without the abstract ctor
/* type SubclassOfBaseClass = (new () => BaseClass<any>) & {
prototype: BaseClass<any>;
getName: () => string;
} */
type IChildrenObj = {
[key: string]: SubclassofBaseClass
}
const Children: IChildrenObj = {
C1: Child1,
C2: Child2,
} // okay
const nums = Object.values(Children)
.map(ctor => new ctor().itemArray.length); // number[]
console.log(nums); // [0, 0]
const names = Object.values(Children)
.map(ctor => ctor.getName()) // string[]
console.log(names); // ["Child1", "Child2"]