推断抽象类的类型

时间:2018-09-12 15:34:21

标签: typescript

我有一个令人费解的案例,我有99%的肯定使用typescript无法解决,而且问题很明显是因为将Typescript代码与不安全的JS代码连接在一起。但是我之前见过在这个网站上发生过奇迹……

我有一些我无法控制但必须使用的JS代码,它采用一个自动生成的抽象类(来自protobuf定义,但这并不重要)进行扩展并创建它。自动生成的类具有d.ts个文件,这是重要的部分,因为我想保留其类型信息以用于自动完成。

因此,让我们从包装扩展并创建抽象类的JS代码开始->

type getCtorType<Ctor> = Ctor extends { new(): infer T } ? T : never;

const initalizeClass = <Ctor extends { new(): any }>(abstractCtor: Ctor): getCtorType<Ctor> => {
    return null as any; //In reality, here there is a call to javascript code that does all the magic
}

因此,举例来说,我有两个类,一个是抽象的,另一个不是:

class Foo {
    someFunc(a: string) {}
}

abstract class Bar {
    someFunc(a: string) { };
}

我们将其初始化:

//This has type inference;
const instance1 = initalizeClass(Foo);
//This is an error
const instance2 = initalizeClass(Bar);

第二行失败,因为抽象类无法满足{ new (): any}的约束,因为它无法创建。

如果我从initalizeClass中删除了此约束,而改用Function之类的东西

const initalizeClassAlternative = (abstractCtor: Function) => {
    return null as any; //In reality, here there is a call to javascript code that does all the magic
}

如果这样做,我将丢失所有类型推断。

有人能想到一种方法/技巧来从传递给函数的抽象类中提取类型吗?以与如何提取常规类的类型类似的方式?


如果您想知道为什么这样的功能还不够好,我真的想输入推断:

const instance2: Bar = initalizeClassAlternative(Bar);

这里是playground link。这个例子更接近我的实际用例,因为这个问题已经太长了,我将其删掉了……但是总之,我正在尝试使用映射类型。

1 个答案:

答案 0 :(得分:1)

在有type inference in conditional types之前,有lookup types。根据{{​​3}},Function接口具有类型prototype的{​​{1}}属性。类(甚至是抽象类)将使用与所讨论类的实例类型相对应的类型来覆盖此属性。因此,作为解决问题的快速方法,您可以检查以下属性:

any

(出于您可能并不在意的美学原因,我将名称从type InstanceType<Ctor> = Ctor extends Function ? Ctor['prototype'] : never; 更改为getCtorType<>,请随时将其改回。) 这使您可以使用第二种方法:

InstanceType<>

对我很好!如果您想排除将非类似declare const initalizeClass: <Ctor extends Function>( abstractCtor: Ctor ) => InstanceType<Ctor>; abstract class Bar { someFunc(a: string) { }; } const bar = initalizeClass(Bar); bar.someFunc("works"); 的{​​{1}}类型传递到class(例如,要求Function属性不为{{1} }),但可能没有必要。

希望有所帮助;祝你好运!