TypeScript:如何指定需要参数的构造函数的类型?

TypeScript:如何指定需要参数的构造函数的类型?,typescript,interface,Typescript,Interface,我已将问题缩小到以下最小示例: //接口: 接口类参数{ x:号码 } 接口类参数输入器{ y:号码 } 类型ClassParameterConstructor=new()=>ClassParameter 类型ClassParameterNederConstructor= 新建(cpc:ClassParameterConstructor)=>ClassParameterNeder //////////////////////////////////////////////////// //实施:

我已将问题缩小到以下最小示例:

//接口:
接口类参数{
x:号码
}
接口类参数输入器{
y:号码
}
类型ClassParameterConstructor=new()=>ClassParameter
类型ClassParameterNederConstructor=
新建(cpc:ClassParameterConstructor)=>ClassParameterNeder
////////////////////////////////////////////////////
//实施:
类MyClassParameter实现ClassParameter{
x=12
外场=27
}
类MyClassParameterNeder实现ClassParameterNeder{
y=19
otherExtraField=29
构造函数(mcpc:new()=>MyClassParameter){}
}
let DoesNetwork:ClassParameterNeederConstructor=MyClassParameterNeeder
TypeScript抱怨最后一行:

let doesntWork: ClassParameterNeederConstructor
Type 'typeof MyClassParameterNeeder' is not assignable to type 'ClassParameterNeederConstructor'.
  Types of parameters 'mcpc' and 'cpc' are incompatible.
    Type 'ClassParameterConstructor' is not assignable to type 'new () => MyClassParameter'.
      Property 'extraField' is missing in type 'ClassParameter' but required in type 'MyClassParameter'.(2322)
input.ts(22, 5): 'extraField' is declared here.
这首先让我想知道为什么这里的依赖关系看起来是相反的,但它实际上是有道理的。在类型
classParameternederConstructor
的声明中,符合该类型的外部构造函数必须接受内部
ClassParameterConstructor
,该构造函数可以构造任何类型的
ClassParameter
,而不仅仅是
MyClassParameter
的专用构造函数。但我该如何解决这个问题呢?在接口中,我不能比在实现中窄,在实现中,我不能只接受任何类型的
ClassParameterConstructor
,实现
MyClassAsParameterNeeder
可能特别需要
MyClassParameter
的构造函数

感谢您的帮助

编辑:

我尝试将@jcalz的解决方案映射到我的实际问题:

在这里,我实际上已经尝试过使用泛型,但到目前为止,我将其放在了新的后面(第26行):

RigidBody:new(shapeClass:new()=>S)=>RigidBodyInterface
这没用。现在我已经将它移动到PhysicInterface的构造函数中(现在的第23行),它可以工作了

但是,现在我必须在泛型参数列表中列出引擎使用的所有抽象类,这有点难看(特别是因为TypeScript没有将泛型参数显示为工具提示),但我想这是有意义的

我也尝试过建立一个类型推断工厂,但最终我没能成功(最后一行抛出一个错误)我认为这也太令人困惑了,我还需要一种方法将物理引擎类的特定于引擎的实现注入到物理引擎类工厂中,所以我认为我将使用方法a

然而:按照现在的实现方式,物理引擎的用户可以访问类的p2特定成员,并且它们也在TypeScript代码完成中列出。是否有一种方法可以将该字段设置为私有,但引擎本身仍然可以访问所有p2字段?我在C++中使用<代码>朋友>代码>… 我现在有了一个可行的解决方案,但我仍然很感谢大家对我如何使工厂正常运转以及整个概念的评论


谢谢

首先,您的
MyClassParameterNeeder
构造函数的代码说它需要一个
MyClassParameter
实例,但看起来您的意图是让它接受一个
MyClassParameter
构造函数。也就是说,
mcpc
不应注释为类型
MyClassParameter
,而应注释为类型MyClassParameter或注释为
new()=>MyClassParameter

class MyClassParameterNeeder implements ClassParameterNeeder {
   y = 19
   otherExtraField = 29
   constructor(mcpc: new () => MyClassParameter) { } // changed here
}
一旦修复了该问题,您仍然会遇到
MyClassParameterNeeder
不是有效的
ClassParameterNeederConstructor
,但现在错误消息至少与您确定的实际问题一致:

let doesntWork: ClassParameterNeederConstructor = MyClassParameterNeeder
//Type 'typeof MyClassParameterNeeder' is not assignable to type 'ClassParameterNeederConstructor'.
//Types of parameters 'mcpc' and 'cpc' are incompatible.
//Type 'new () => ClassParameter' is not assignable to type 'new () => MyClassParameter'.
//Property 'extraField' is missing in type 'ClassParameter' but required in type 'MyClassParameter'.

因此,听起来您的
MyClassParameterNeeder
实现就是您想要的:
mcpc
必须具体构造
MyClassParameter
实例,而不仅仅是任何旧的
ClassParameter
。这意味着您的
classParameterNederConstructor
类型不适合您使用

假设您创建了一个新的
ClassParameter
子类和一个关联的“needer”:

请注意,在不丢失所关心的信息的情况下,您不能期望使用同一类型来描述
MyClassParameterNeeder
另一个classparameterneeder
。如果您试图将其表示为普通类型,则需要将其扩展到某种类型安全但无用的类型:

type UselessClassParameterNeederConstuctor =
   new (cpc: new () => never) => ClassParameterNeeder

const uselessMine: UselessClassParameterNeederConstuctor = MyClassParameterNeeder;
const uselessAnother: UselessClassParameterNeederConstuctor = AnotherClassParameterNeeder;
new uselessMine(MyClassParameter); // error, can't call it
或者在某个地方使用不健康的东西来获得你可以使用但会很危险的东西:

type UnsoundClassParameterNeederConstuctor =
   new (cpc: new () => any) => ClassParameterNeeder

const unsoundMine: UnsoundClassParameterNeederConstuctor = MyClassParameterNeeder;
const unsoundAnother: UnsoundClassParameterNeederConstuctor = AnotherClassParameterNeeder;
new unsoundMine(AnotherClassParameter); // no error, but there should be

您需要一个类型,该类型可以根据所需的
ClassParameter
子类构造函数而更改。这意味着
classParameterNederConstructor
应该是:

类型ClassParameterNederConstructor=
新建(cpc:new()=>C)=>classParameterNeder
常量genericMine:ClassParameterNederConstructor=
MyClassParameterNeeder;

const genericAnother:classparameternederconstructor

采用构造函数的构造函数类型是编写的
type C=new(cptime:new(x:SomeParam)=>IPrime)=>I
。不需要中间类型来描述itThanks,这是我试图减少混乱的嵌套的一点。非常感谢,这就解决了它!我也解决了这个问题。
type UselessClassParameterNeederConstuctor =
   new (cpc: new () => never) => ClassParameterNeeder

const uselessMine: UselessClassParameterNeederConstuctor = MyClassParameterNeeder;
const uselessAnother: UselessClassParameterNeederConstuctor = AnotherClassParameterNeeder;
new uselessMine(MyClassParameter); // error, can't call it
type UnsoundClassParameterNeederConstuctor =
   new (cpc: new () => any) => ClassParameterNeeder

const unsoundMine: UnsoundClassParameterNeederConstuctor = MyClassParameterNeeder;
const unsoundAnother: UnsoundClassParameterNeederConstuctor = AnotherClassParameterNeeder;
new unsoundMine(AnotherClassParameter); // no error, but there should be
type ClassParameterNeederConstructor<C extends ClassParameter> =
   new (cpc: new () => C) => ClassParameterNeeder

const genericMine: ClassParameterNeederConstructor<MyClassParameter> =
  MyClassParameterNeeder;
const genericAnother: ClassParameterNeederConstructor<AnotherClassParameter> =
  AnotherClassParameterNeeder;

new genericMine(MyClassParameter); // okay, as desired
new genericAnother(AnotherClassParameter); // okay, as desired
new genericMine(AnotherClassParameter); // error, as desired
const asClassParameterNeederConstructor =
   <C extends ClassParameter>(c: ClassParameterNeederConstructor<C>) => c;

const inferredMine = asClassParameterNeederConstructor(MyClassParameterNeeder);
const inferredAnother = asClassParameterNeederConstructor(AnotherClassParameterNeeder);
new inferredMine(MyClassParameter); // okay, as desired
new inferredAnother(AnotherClassParameter); // okay, as desired
new inferredMine(AnotherClassParameter); // error, as desired