繁体   English   中英

具有通用返回类型的方法

[英]Method with generic return type

在 TypeScript 中,是否可以将以下getComponent方法设为通用,以便在调用时将as SkinComponent丢弃?

我认为这里的部分问题可能是我传入的是IComponentConstructor ,但我想要返回的是IComponent 所以我不确定如何使用 generics 来表示。

const skinComponent = gameObject.getComponent(SkinComponent) as SkinComponent;

skinComponent.methodOnlyAvailableOnSkinComponent();
export class GameObject {
    
    components: IComponent[];

    public getComponent(
        ComponentType: IComponentConstructor
    ): IComponent | undefined {

        return this.components.find(c => c instanceof ComponentType);
    }
}

我尝试了几种不同的方法,例如下面的方法,但我似乎总是以以下错误告终。

public getComponent<T extends IComponent>(
    ComponentType: IComponentConstructor<T>
): T | undefined {
    
   return this.components.find(c => c instanceof ComponentType);
}
Type 'IComponent | undefined' is not assignable to type 'T | undefined'.
Type 'IComponent' is not assignable to type 'T'.
'IComponent' is assignable to the constraint of type 'T', but 'T'
could be instantiated with a different subtype of constraint 'IComponent'.

PS:关于IComponentConstructorIComponent ,请看我之前的 StackOverflow 帖子: Constructor in interface

array.find()不是泛型方法,因此不会缩小类型。 这意味着array.find()始终返回数组的成员类型类型。

const strings: string[] = ['a', 'b', 'c']
const a = strings.find(str => str === 'a') // type is string | undefined, and not "a"

所以this.components.find()将返回一个IComponent因为这是数组的成员类型。 并且不能假定IComponentIComponent的任何特定子类


但是, if语句确实缩小了类型。 所以我可能会将其更改为一个简单的循环并提前返回:

    public getComponent<T extends IComponent>(
        ComponentType: IComponentConstructor<T>
    ): T | undefined {
        for (const c of this.components) {
            if (c instanceof ComponentType) return c
        }
        return
    }

现在cif语句将该类型缩小到T之后返回,其他一切正常。

const gameObject = new GameObject()
const skinComponent = gameObject.getComponent(SkinComponent);
skinComponent?.methodOnlyAvailableOnSkinComponent(); // works

看游乐场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM