TypeScript变量意外转换问题:参数异常变为Arguments对象
TypeScript分页数据加载中参数意外转为Arguments对象的问题
我在TypeScript实现服务器分页数据加载时遇到了一个诡异问题:小型测试程序运行完全正常,但在大型应用里,传入的对象参数q会被意外转换成Arguments对象。
测试程序(表现正常)
#!/usr/bin/env node var q = {page: '1', results: '1'}; var si = '1'; interface aqm { [key: string]: string | number; } function uasekq(si: string, q: aqm = {}, foo: string) { console.log(si); console.log(q); console.log(foo); } uasekq(si, q, "abc");
大型应用编译后的JavaScript代码
function uasekq(si) { var q = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}, options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}; var temp = (0,_cuaq__WEBPACK_IMPORTED_MODULE_0__["default"])((0,_shsosm__WEBPACK_IMPORTED_MODULE_1__["default"])({ queryKey: [ "s", si, "aek" ], pathname: "/v3/keys/storage/:si", q: (0,_shsospm__WEBPACK_IMPORTED_MODULE_2__["default"])((0,_shsosm__WEBPACK_IMPORTED_MODULE_1__["default"])({}, q), { si: si }) }, options)); return temp; }
异常现象
两处传入的q都是{page: '1', results: '25'},但大型应用中函数接收到的q却是一个Arguments对象:
Arguments(2) [undefined, {…}, callee: (...), Symbol(Symbol.iterator): ƒ] 0: undefined 1: {page: '1', results: '25'} callee: (...) length: 2 Symbol(Symbol.iterator): ƒ values() get callee: ƒ () set callee: ƒ () [[Prototype]]: Object
原始TypeScript函数及调用代码
// 调用代码(来自另一个文件): // const { d: ek, il } = uasekq(si, q); interface aqm { [k: string]: string | number; } function uasekq( si: string, q: aqm = {}, o: p<uaqo<pr<ek>>> = {} ) { var temp = uaq<pr<ek>>({ qk: ['s', si, 'aek'], p: '/v/k/s/:si', q: { ...q, si }, ...o, }); return temp; }
环境与尝试的操作
当前使用typescript@4.9.5,尝试升级到5.3.3时出现编译错误,回退到4.9.5后编译正常但问题依旧。
原因分析
参数解析与
arguments对象冲突:
大型应用编译后的代码仅显式声明第一个参数si,后续参数通过arguments对象获取。如果依赖的工具函数(比如_shsospm__WEBPACK_IMPORTED_MODULE_2__["default"])内部错误地将arguments当作普通对象处理,或者在对象合并时意外引入了arguments,就会导致q被替换成Arguments对象。打包/转译工具的bug:
大型应用使用Webpack打包,可能存在旧版转译插件(如@babel/plugin-transform-parameters)在处理默认参数时的逻辑错误,导致参数解析异常,把arguments对象错误赋值给了q。工具函数的副作用:
代码中调用的_shsosm或_shsospm工具函数,如果内部存在修改传入参数、错误引用当前函数arguments的逻辑,会直接污染q参数。
解决方案
- 显式声明所有参数:修改TypeScript函数,确保所有参数都显式声明,避免依赖
arguments隐式获取参数,编译后的代码逻辑会更清晰,减少冲突概率。 - 升级转译插件:检查Webpack/Babel配置,将相关转译插件升级到兼容当前TypeScript版本的最新版,修复旧版插件的参数处理bug。
- 隔离参数引用:在函数开头复制一份
q参数,避免后续工具函数操作影响原始参数:function uasekq( si: string, q: aqm = {}, o: p<uaqo<pr<ek>>> = {} ) { const safeQ = {...q}; // 复制参数,避免原对象被污染 var temp = uaq<pr<ek>>({ qk: ['s', si, 'aek'], p: '/v/k/s/:si', q: { ...safeQ, si }, ...o, }); return temp; } - 排查工具函数:检查
_shsospm和_shsosm的实现,确认内部是否存在错误引用arguments或修改传入对象的逻辑。
内容的提问来源于stack exchange,提问作者dstromberg
相关产品推荐
相关产品推荐

