如何在 Typescript 中检查数组的类型?

tt9*_*tt9 5 arrays typescript

我有一个带有以下签名的函数

public async sequenceAnimations(animations: AnimationPlayer[] | AnimationTracker[]): Promise<any>
Run Code Online (Sandbox Code Playgroud)

在函数本身中,我想根据它是 AnimationPlayer 数组还是 AnimationTracker 数组进行分支,所以我尝试了以下方法:

let mappedAnimations = animations;
if (animations instanceof Array<AnimationTracker>) {
    mappedAnimations = animations.map(anim => anim.animationPlayer)
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我试图允许调用者传递一个 AnimationPlayer 数组或一个包含 animationPlayer 实例的 AnimationTracker 数组。但是在使用类型检查数组的实例时出现错误

“instanceof”表达式的右侧必须是“any”类型或可分配给“Function”接口类型的类型。

另外,自动完成功能不会在 if 块中注册数组的类型,因此我认为我无法像这样检查数组类型。

确定传递的数组类型的正确方法是什么?

Tit*_*mir 5

您不能instanceof与带有类型参数的泛型类型一起使用。编译后,所有泛型都会被删除,因此animations instanceof Array<AnimationTracker>会变成animations instanceof Arraywhich 不会执行您期望的操作。

由于在 Javscript 中数组不是类型化的,因​​此没有内置的方法来区分数组AnimationPlayer[]AnimationTracker[]数组是否为空,因此在运行时它们实际上是无法区分的。但是,您可以创建一个自定义类型保护,它使用数组中的第一个非空项来确定类型。对于空数组,这总是会返回false,但在大多数情况下这可能是一个不错的解决方案:

function isArrayOf<T>(array:any[], cls: new (...args: any[]) => T) : array is T[] {
    for(let item of array) {
        if(item != null) return  item instanceof cls;
    }
    return  false;
}
async function sequenceAnimations(animations: AnimationPlayer[] | AnimationTracker[]): Promise<any> {
    let mappedAnimations = animations;
    if (isArrayOf(animations, AnimationTracker)) {
        // animations is AnimationTracker[]
        mappedAnimations = animations.map(anim => anim.animationPlayer);
    }
}
Run Code Online (Sandbox Code Playgroud)