我有一个带有以下签名的功能
public async sequenceAnimations(animations: AnimationPlayer[] | AnimationTracker[]): Promise<any>
在函数本身中我想基于它是否是AnimationPlayer数组或AnimationTracker数组进行分支,所以我尝试了这个:
let mappedAnimations = animations;
if (animations instanceof Array<AnimationTracker>) {
mappedAnimations = animations.map(anim => anim.animationPlayer)
}
正如您所看到的,我正在尝试允许调用者传递AnimationPlayer数组或具有animationPlayer实例的AnimationTracker数组。但是在使用类型
检查Array的instanceof时出错&#39;实例的右侧。表达式必须是&#39; any&#39;或者可以分配给&#39;功能&#39;界面类型。
自动完成也没有在if块中注册数组的类型,所以我假设我不能像这样检查数组类型。
确定传递的数组类型的正确方法是什么?
答案 0 :(得分:3)
您不能将instanceof
与带有类型参数的泛型类型一起使用。编译完成后,所有泛型都将被删除,因此animations instanceof Array<AnimationTracker>
将变为animations instanceof Array
,这将无法达到您的预期。
由于在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);
}
}
答案 1 :(得分:1)
简短回答:你不能。
TypeScript的主要思想是在编译时添加类型,并在编译后发出纯JavaScript代码。 JavaScript本身不支持高级类型检查,因此您只能选择在运行时进行鸭子输入。