TypeScript中无需转换函数解决数字字面量类型数组reduce报错
解决TypeScript中DiceNumber累加的类型错误
问题背景
给定以下代码:
type DiceNumber = 1 | 2 | 3 | 4 | 5 | 6; const rollDice = (): DiceNumber => ( Math.floor(Math.random() * (6 - 1) + 1) as DiceNumber )
执行累加代码时触发类型错误:
const result = [...Array(4)].map(rollDice).reduce((acc, i) => acc + i)
错误提示:
acc: DiceNumber Type 'number' is not assignable to type 'DiceNumber'.ts(2322)i: DiceNumber Type 'number' is not assignable to type 'DiceNumber'.ts(2322)
当前通过额外转换函数解决,但希望找到更简洁的方案。
无需额外转换函数的解决方案
方案1:给reduce指定number类型的初始值
这是最简洁的方案,利用TypeScript的类型推断自动修正类型:
const result = [...Array(4)].map(rollDice).reduce((acc, i) => acc + i, 0)
原理:当给reduce传入初始值0(number类型)时,TypeScript会推断累加器acc的类型为number,而DiceNumber作为number的字面量子类型,可以直接与number进行加法运算,最终返回结果的类型也是number,完全匹配类型要求。
方案2:显式指定reduce的泛型返回类型
如果需要更明确地控制类型,可以直接给reduce指定泛型参数:
const result = [...Array(4)].map(rollDice).reduce<number>((acc, i) => acc + i, 0)
原理:通过泛型<number>强制指定reduce的返回类型为number,结合初始值0让累加器类型与返回类型保持一致,避免类型不匹配。
方案3:在map中直接断言类型(无需额外函数)
如果不想修改reduce的写法,可以在map阶段直接将DiceNumber断言为number:
const result = [...Array(4)].map(rollDice).map(d => d as number).reduce((acc, i) => acc + i)
原理:将每个DiceNumber元素直接断言为number,后续reduce处理的就是纯number数组,自然不会有类型错误。
总结
最推荐方案1,仅需添加初始值0就能解决问题,代码简洁且符合TypeScript的类型推断逻辑,不需要额外的断言或转换代码。
内容的提问来源于stack exchange,提问作者Khoa Nguyen
相关产品推荐
相关产品推荐

