You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript函数向联合类型数组推入错误类型为何无编译错误?

为什么这段TypeScript代码能无错误编译,以及如何检测这类类型不安全问题

这段代码能编译通过,核心原因是TypeScript在默认编译模式下,对数组类型采用了协变的类型兼容性规则:

  • string是StrNum(string | number)的子类型,所有string类型的值都符合StrNum的约束;
  • 默认模式下,若类型A是B的子类型,那么A[]会被视为B[]的子类型,所以string[]可以赋值给StrNum[]类型的参数。

但这里存在明显的类型安全隐患:StrNum[]的push方法允许传入number类型值,而你传入的strArr本质是string[]数组。调用arr.push(1)后,原本只能存储字符串的数组被插入了数字,导致运行时数组的实际类型与声明的string[]不符。

如何检测并避免这类问题

  • 开启--strictFunctionTypes编译选项
    这个选项会启用更严格的函数参数类型检查。在该模式下,数组的类型兼容性会遵循函数参数的逆变规则:StrNum[]的push方法接受string | number,而string[]的push仅接受string,此时string[]无法赋值给StrNum[],编译器会直接报错,阻止不安全的赋值操作。

  • 使用只读数组约束参数
    如果函数不需要修改数组,可将参数类型改为readonly StrNum[],此时push方法会直接报错(只读数组不支持修改操作),从根源避免类型污染:

    type StrNum = string | number;
    const strArr: string[] = [];
    function addToArray(arr: readonly StrNum[]): void {
      // arr.push(1); // 报错:Property 'push' does not exist on type 'readonly StrNum[]'
    }
    addToArray(strArr);
    
  • 避免使用宽松的数组类型参数
    尽量不要用联合类型数组作为允许修改的参数类型,或者在需要修改时,确保传入的数组本身就兼容联合类型(比如直接声明StrNum[]类型的数组)。

内容的提问来源于stack exchange,提问作者jerichaux

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 09:52:46