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

为什么Object.assign创建的数组类型为never[] & number[]?

TypeScript 中 Object.assign 拷贝数组的类型问题解答

先贴问题相关代码方便对照:

const arr = [1,2,3]
const res1 = arr.slice()
const res2 = Object.assign([],arr)

为什么 res2 的类型包含 never[]

  • TypeScript 对Object.assign的内置类型签名为:Object.assign<T, U>(target: T, source: U): T & U,返回值是入参中目标对象类型和源对象类型的交叉类型。
  • 代码中传入的第一个目标参数是字面量空数组[],在没有显式指定类型的场景下,TypeScript 默认会将空数组的类型推断为never[]:含义是这是一个不允许放入任何非never类型元素的数组。
  • 第二个源参数arr的类型是number[],两者交叉后返回值类型自然就是never[] & number[]。
  • 对比之下数组原生的slice方法的类型签名是slice(start?: number, end?: number): T[],直接返回原数组同类型的数组,所以res1的类型就是和原数组一致的number[]。

交叉类型 & 为什么能让值同时符合两种类型要求

首先要明确:TypeScript 的交叉类型不是要求值同时属于两个独立的类型,而是要求值同时具备两个类型的所有属性、满足两个类型的所有使用规则。

  • never是 TypeScript 中的底类型,never[]的结构和普通数组完全一致,仅对元素的写入规则做了限制。
  • 这里的never[] & number[]看起来存在类型冲突,实际上是 TypeScript 没有对数组类交叉类型做额外的简化,只是保留了类型计算的原始结果,实际使用上这个交叉类型和普通的number[]完全等价:你可以正常读取number类型的元素、写入number类型的值,不会有任何类型报错。
  • 从实际值的角度看,Object.assign([], arr)是将arr的所有可枚举属性(索引、length等)复制到空数组上,最终得到的数组本身就完全符合number[]的要求,自然可以匹配交叉类型的规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 23:15:09