Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 是否存在从派生类推断基类类型的方法?_Typescript_Generics - Fatal编程技术网

Typescript 是否存在从派生类推断基类类型的方法?

Typescript 是否存在从派生类推断基类类型的方法?,typescript,generics,Typescript,Generics,我正在为我的TypeScript库开发一项功能,并且一直在解决这个打字问题。请看以下示例: 类基类{…} 类用户扩展基{…} 类产品扩展了基{…} 类CompletelyUnrelated{…} 函数someFunction(源代码:TModel,base:{what_to_type_here}){…}; //期望结果 someFunction(用户、基);//作品 某些功能(产品、基础);//作品 someFunction(完全不相关,基本);//错误 某些功能(用户、产品);//错误 某些功

我正在为我的
TypeScript
库开发一项功能,并且一直在解决这个打字问题。请看以下示例:

类基类{…}
类用户扩展基{…}
类产品扩展了基{…}
类CompletelyUnrelated{…}
函数someFunction(源代码:TModel,base:{what_to_type_here}){…};
//期望结果
someFunction(用户、基);//作品
某些功能(产品、基础);//作品
someFunction(完全不相关,基本);//错误
某些功能(用户、产品);//错误
某些功能(产品、用户);//错误
someFunction(用户,完全不相关);//错误
为了进一步解释所需的输出,我希望使用
someFunction()
期望
User
Base
作为其参数,因为
User扩展了Base
。与
产品
基础
相同。有没有(甚至)方法来实现这一点?有什么接近我想要实现的吗

我试过:

interface-Constructible{//一个用于注释新的可构造类型的接口(任意,放在这里作为上下文)
新(…args:any[]):TModel;
}
类型BaseConstructible=TModel扩展推断TBase?可建造的:任何;
但是,这不起作用,我总是得到
可构造的
,结果是:

type Test=BaseConstructible;//返回可构造的
任何帮助/指导都将不胜感激。谢谢

UPDATE:正如@jcalz所指出的,
TypeScript
有一个结构化的类型系统,我也知道这一点@jcalz的回答是完全真实和正确的。然而,这并不是我想要的(也许在TypeScript中根本不可能)。以下是一个案例:

函数另一个函数(来源:可构造){
返回(基本:可构造)=>{
//功能体
}
}
其他功能(用户)(产品);//无误

TypeScript
根本不知道或无法从
t模型扩展TBase
推断
TBase
。我想知道是否有办法让
TypeScript
推断
TBase

第一件事:TypeScript的类型系统是;粗略地说,这意味着如果两个类型具有相同的形状,那么它们是相同的类型,即使这些类型具有不同的声明。这与爪哇、C++、或C中的标称类型形成了鲜明的对比,其中“代码>类A{{} /Class>和<代码>类B{} <代码>是不同类型,仅仅因为它们有不同的声明。 例如,如果TypeScript中的示例类为,则它们将被视为与空接口
{}
相同,并且彼此相同。因此,您可能会看到一些奇怪的行为,比如说,
CompletelyUnrelated
,尽管名称不同,实际上被认为与其他类(如
Base
)的类型相同。如果您希望编译器将两个类视为不同的,那么仅具有不同的类声明是不够的;您需要这两个类具有不同的成员(或者它们需要具有
private
protected
成员,这将提供更多的功能)

以下是一些具有足够属性的类,
Base
User
Product
CompletelyUnrelated
以您想要的方式进行关联:

class Base {
  base = "base"
}

class User extends Base {
  user = "user"
}
class Product extends Base {
  product = "product"
}

class CompletelyUnrelated {
  completelyUnrelated = "whatevz";
}

现在我们可以为
someFunction()
编写类型签名。我将其分为两种类型:
T
,表示
base
构造函数的实例类型;和
U
,表示
构造函数的实例类型。我们希望
U
,以便它
扩展T
,并且我们希望
参数成为构造函数:

function someFunction<T, U extends T>(
  source: new (...args: any) => U,
  base: new (...args: any) => T
) { return null! };
看起来不错
someFunction()
在您希望的地方成功或失败。好吧,希望这会有帮助;祝你好运


更新:

如果您想将
someFunction()
分解为一个名为
anotherFunction()
的版本,则需要执行更多的类型转换来实现这一点。主要问题是编译器希望
另一个函数(sometor)
的返回值是一个确定的类型,因此需要将该类型表示为只允许与
sometor
对应的类实例类型的超类型

从概念上讲,您希望类型看起来像
(source:new(…args:any)=>U)=>(base:new(…args:any)=>T)=>void
,其中
T super U
是表示下限的假设语法,而不是由
T extensed U
表示的上限。所以
T super U
U extends T
应该是同一个意思

不幸的是,TypeScript中没有
T super U
下限约束。获取相关的功能请求。您可以使用条件类型对这种行为进行排序。您可以编写
T extends([U]extends[T]?unknown:never)>
:而不是
T super U
:这将执行
U extends T
检查(
[U]extends[T]
关闭
U
中的联合,如果成功,则变成
T extends unknown
,这始终是真的,如果失败,它将变成
T extends never
,这本质上总是错误的。那么像这样,

function anotherFunction<U>(source: new (...args: any) => U) {
  return <T extends ([U] extends [T] ? unknown : never)>(base: new (...args: any) => T) => {
  }
}
这正是您想要的,只是可能错误很奇怪:“
Base
不可分配给
never
”,虽然为true,但在某种程度上没有帮助“
CompletelyUnrelated
不可分配给
Base
”。所以这里还有一点限制

好吧,希望这能再次帮助你。祝你好运


第一件事:TypeScript的类型系统是;粗略地说,这意味着如果两种类型具有相同的形状,那么它们是相同的
function anotherFunction<U>(source: new (...args: any) => U) {
  return <T extends ([U] extends [T] ? unknown : never)>(base: new (...args: any) => T) => {
  }
}
anotherFunction(User)(Base); // okay
anotherFunction(Product)(Base); // okay
anotherFunction(Base)(Product); // error!
// -----------------> ~~~~~~~
// Type 'Product' is not assignable to type 'never'
anotherFunction(CompletelyUnrelated)(Base); // error!
// --------------------------------> ~~~~
// Type 'Base' is not assignable to type 'never'
anotherFunction(User)(Product); // error!
anotherFunction(Product)(User); // error!
anotherFunction(User)(CompletelyUnrelated); // error!