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"]