Hack类型转换无报错咨询:为何传入非匹配数组未触发错误?
为什么传入一维数组给Hack函数没触发类型错误?
嘿,这个问题我之前也踩过坑,其实和Hack类型系统的两个关键细节息息相关,我给你拆解清楚:
首先,静态类型检查才是Hack类型校验的核心
你定义的Points是array<array<int, int>>,说白了就是「装着整数数组的数组」,但你传的[0, 0]是个纯整数的一维数组,这俩在类型层面根本不兼容。
但Hack的类型校验主要靠静态分析工具hh_client,不是光看运行时。如果你只是直接跑代码,没先执行hh_client检查,自然看不到错误提示:
- 要是开了strict模式(在
.hhconfig里设strict = true),hh_client会直接抛出致命错误,根本不让你运行这段代码; - 要是在partial模式下,它会给你个警告,但还是允许代码跑起来。
你可以试试在项目根目录敲个hh_client,肯定能看到类似这样的提示:
Argument 1 passed to printPoint() must be of type Points, array<int, int> given
其次,运行时泛型类型被擦除了
Hack的泛型参数在运行时是会被「丢掉」的——也就是说,array<array<int, int>>到了运行时就只是个普通的array,没人记得它本来要求元素必须是数组。
所以你传一维数组进去,运行时只会检查它是不是数组,不会管维度对不对、元素类型符不符合。刚好你的函数里直接取$point[0]和$point[1],这个一维数组刚好有这两个索引,自然能输出整数,不会报错。
怎么避免这种情况?
想要彻底拦住这类问题,给你几个建议:
- 果断开strict模式,让静态检查强制拦截类型不匹配的情况,从根源上杜绝;
- 写代码养成习惯,每次改完先跑
hh_client检查,提前揪出类型问题; - 要是需要运行时也严格校验,可以手动在函数里加维度检查,比如:
function printPoint(Points $point): void { if (!is_array($point[0]) || !is_array($point[1])) { throw new \TypeError("Expected a 2D array (array of arrays)"); } var_dump($point[0], $point[1]); }
这样不管是静态检查还是运行时,都能及时把不符合要求的输入拦下来。
内容的提问来源于stack exchange,提问作者hunomina
相关产品推荐
相关产品推荐

