我如何告诉typescript我的函数返回一个由特定类扩展的类?

我如何告诉typescript我的函数返回一个由特定类扩展的类?,typescript,Typescript,考虑以下类别: class A { constructor($elem: JQuery<HTMLElement>) { $elem.data('plugin', this); } inheritedMethod() { ... } } class B extends A { constructor($elem: JQuery<HTMLElement>) { super($elem)

考虑以下类别:

class A {
    constructor($elem: JQuery<HTMLElement>) {
        $elem.data('plugin', this);
    }

    inheritedMethod() {
        ...
    }
}

class B extends A {
    constructor($elem: JQuery<HTMLElement>) {
        super($elem);
    }

    specificMethodB() {
        ...
    }
}

class C extends A {
    constructor($elem: JQuery<HTMLElement>) {
        super($elem);
    }
}

getAishClass($elem: JQuery<HTMLElement>): A {
    return $elem.data('plugin');
    // this function will return either a class B or a class C
}


const $bDiv = jQuery("<div></div>");
const $cDiv = jQuery("<div></div>");

new B($bDiv);
new C($cDiv);

const thisIsAC = getAishClass($cDiv);

thisIsAC.specificMethodC(); // this tells me that I have an error, A does not implement this method
A类{
构造函数($elem:JQuery){
$elem.data('plugin',this);
}
继承方法(){
...
}
}
B类扩展了A类{
构造函数($elem:JQuery){
超级($elem);
}
具体方法b(){
...
}
}
C类扩展了{
构造函数($elem:JQuery){
超级($elem);
}
}
getAishClass($elem:JQuery):一个{
返回$elem.data('plugin');
//此函数将返回类B或类C
}
const$bDiv=jQuery(“”);
const$cDiv=jQuery(“”);
新B(比索四美元);
新的C(cDiv美元);
const thisIsAC=getAishClass($cDiv);
thisIsAC.specificMethodC();//这说明我有一个错误,A没有实现这个方法
我可以告诉
getAishClass
它返回一种类型的
any
,但是有没有一种方法可以明确地指定,函数返回的值将是一个类,它肯定扩展了
类a

基本上,在上面的示例中,我(程序员)和程序“可以”知道
getAishClass
将返回
C
的实例。但是考虑到上面的示例,在某些情况下,我将对jQuery元素调用
getAishClass
方法,我不知道它实现了哪种
a
。在这些情况下,我希望至少为
A
类中的方法获得类型提示,但在所有其他情况下,我不希望ts抱怨函数未实现。

`
`

class A {
  someMethod() {}
}

class B extends A {
  someMethodB() {}
}

class C extends A {
  someMethodC() {}
}

class D {}

function myfunc(): A {
  return new B();
}

const btype = <B>myfunc();
btype.someMethodB(); // no problem to IDE here

function myfunc2(): A {

    // return new A(); // this is fine.

    // return new B(); // also fine

    // return new C(); // also fine

    // return new D(); // this is not fine, ts will complain. 

}
甲级{ someMethod(){} } B类扩展了A类{ someMethodB(){} } C类扩展了{ someMethodC(){} } 类D{} 函数myfunc():A{ 返回新的B(); } 常量btype=myfunc(); btype.someMethodB();//在这里使用IDE没有问题 函数myfunc2():A{ //返回新的A();//这很好。 //返回新的B();//也可以 //返回新的C();//也可以 //return new D();//这不好,ts会抱怨的。 }
您正在做的是。。。当您调用
new B(elem)
时,您希望编译器对
elem
的类型做些什么,以记住它是用
new B()调用的。这不是TypeScript的正常工作方式

你可以,可以这样做,这样当你调用一个函数作为参数时,
elem
的类型就会缩小。不幸的是,您不能使用构造函数,只能使用函数或方法。这意味着我们需要创建自己的
新的类似的函数,该函数采用构造函数和JQuery元素,并缩小该元素类型:

function magicNew<T>(ctor: new (e: JQuery<HTMLElement>) => T, elem: JQuery<HTMLElement>):
    asserts elem is JQuery<HTMLElement> & { __plugindata__: T } {
    new ctor(elem);
}
这里我们看的是传入的
$elem
。如果编译器认为它有一个
\uuuuu plugindata\uuuu
属性,那么它会给我们该属性类型;否则它只会给我们一个
A
。如果编译器认为幻影属性在那里,我们就把它取出来

我认为,这给了你想要的行为:

const $bDiv = jQuery("<div></div>");
const $cDiv = jQuery("<div></div>");

magicNew(B, $bDiv); // do this instead of new B($bDiv)
magicNew(C, $cDiv); // do this instead of new C($cDiv)

const thisIsAC = getAishClass($cDiv);

thisIsAC.specificMethodC(); // no error
const$bDiv=jQuery(“”);
const$cDiv=jQuery(“”);
magicNew(B,$bDiv);//这样做,而不是新的B($bDiv)
magicNew(C$cDiv);//这样做而不是新的C($cDiv)
const thisIsAC=getAishClass($cDiv);
thisIsAC.specificMethodC();//无误

值得吗?它有许多移动的碎片,很奇怪,可能很脆弱。如果这是为了某段生产代码,我会远离它。如果是个人用的,我可能会用。无论如何,我希望它能让你了解TypeScript能力的局限性和优势

祝你好运


嗯,只是
A
?或者,如果您关心扩展,您可能会
B | C
?也许我不确定你在说什么asking@jcalz我有很多类扩展了
a
类,将来我还会有更多的类。如果该函数知道它返回了扩展
A
类的内容,就足够了。我的问题是,基本上,我可以告诉函数它返回
A
类的一个实例,但是我的IDE会抱怨我是否想分别使用
B
C
类的方法。我将用更多的信息更新我的问题。然后在调用
getAishClass
时,您必须将结果转换为
B
C
;只有调用代码知道实例实际应该是哪个派生类。除非可以从参数中找出返回哪个派生类?这个问题是否依赖于JQuery?如果是,则应贴上标签;如果不是,示例代码应该被制作成一个不依赖于它的配置文件(或者至少包括所有必要的配置文件)。理想情况下,任何代码都应该可以拖放到一个独立的IDE中,就像这样,这样我们就可以轻松地使用它了。
$bDiv
$cDiv
的类型完全相同,因此Typescript无法区分传入
$cDiv
和传入
$bDiv
。我认为您唯一的选择是将constthisisac=getAishClass($cDiv)编写为C,然后您可以使用
C
特定的方法。
const $bDiv = jQuery("<div></div>");
const $cDiv = jQuery("<div></div>");

magicNew(B, $bDiv); // do this instead of new B($bDiv)
magicNew(C, $cDiv); // do this instead of new C($cDiv)

const thisIsAC = getAishClass($cDiv);

thisIsAC.specificMethodC(); // no error