如何根据数组元素类型重写Array的push方法?
TypeScript中根据数组元素类型处理push的正确方式
你的代码里用instanceof Array<Foo>和instanceof Array<Bar>是无效的——TypeScript的泛型信息在编译为JavaScript后会被完全擦除,运行时根本不存在Array<Foo>或Array<Bar>这类具体类型,所以这两个判断永远不会生效。
下面是几种可行的解决方法:
方法一:自定义类型守卫函数
通过检查数组元素的结构来确定数组类型,同时让TypeScript能正确推断类型:
interface Foo { id: number } interface Bar { name: string } // 判断数组是否为Foo[]的类型守卫 function isFooArray(arr: unknown): arr is Foo[] { return Array.isArray(arr) && arr.every(item => typeof item === 'object' && item !== null && 'id' in item && typeof (item as Foo).id === 'number' ); } // 判断数组是否为Bar[]的类型守卫 function isBarArray(arr: unknown): arr is Bar[] { return Array.isArray(arr) && arr.every(item => typeof item === 'object' && item !== null && 'name' in item && typeof (item as Bar).name === 'string' ); } function func1(array_var: Foo[] | Bar[]) { if (isFooArray(array_var)) { array_var.push({ id: 10 }); } else if (isBarArray(array_var)) { array_var.push({ name: "Stack" }); } }
方法二:通过数组元素特征快速判断(适合非空数组)
如果能确定数组不为空,可以通过第一个元素的属性来推断类型:
interface Foo { id: number } interface Bar { name: string } function func1(array_var: Foo[] | Bar[]) { // 处理空数组的业务逻辑,比如默认处理或抛出错误 if (array_var.length === 0) return; const firstItem = array_var[0]; if ('id' in firstItem && typeof firstItem.id === 'number') { (array_var as Foo[]).push({ id: 10 }); } else if ('name' in firstItem && typeof firstItem.name === 'string') { (array_var as Bar[]).push({ name: "Stack" }); } }
方法三:扩展Array的push方法(利用类型推断)
如果你的目标是给数组添加一个类型安全的push方法,不需要运行时判断,直接通过TypeScript的类型约束实现:
interface Foo { id: number } interface Bar { name: string } declare global { interface Array<T> { pushTyped(item: T): void; } } Array.prototype.pushTyped = function<T>(this: T[], item: T) { this.push(item); }; // 使用示例 const fooList: Foo[] = []; fooList.pushTyped({ id: 10 }); // 类型校验通过 const barList: Bar[] = []; barList.pushTyped({ name: "Stack" }); // 类型校验通过
内容的提问来源于stack exchange,提问作者sql_dummy
相关产品推荐
相关产品推荐

