TypeScript报void类型无法赋值给ActionType类型如何解决
报错原因
你期望的写法存在本质的执行时机错误:
- 原箭头函数写法:
action字段存储的是函数引用,只有当action被触发时才会执行内部的optionsActionConstructor调用,符合ActionType的函数类型要求 - 你尝试的简化写法:代码在对象初始化阶段就会立刻执行
optionsActionConstructor(MenuType.DRAW, GeometryType.CIRCLE),把函数的返回值(你定义的返回值是void)赋值给action字段,相当于给需要函数类型的字段传了空值,TS抛出类型错误完全符合预期,就算强行忽略类型校验,运行时触发action也会报「不是函数」的错误。
另外你写的简化示例里属性值末尾多写了分号,对象属性之间应该用逗号分隔。
可行解决方案
方案1:柯里化改造原函数(最贴合你的简化需求)
把optionsActionConstructor改造成接收参数后返回符合ActionType签名的函数,既保留你想要的简洁写法,又能保证执行时机正确、类型匹配:
const optionsActionConstructor = ( type: MenuType.DRAW, tool: DrawGeometryType | OtherToolsType, ): ActionType => { // 返回待执行的函数,闭包保存传入的type、tool参数 return () => { openedLeftMenuVar({ type, tool }); if (isAOtherToolsType(tool)) { mapAnnotationsModalStatusVar({ open: true, category: tool, annotation: null, }); } if (isAGeometryType(tool)) { drawAnnotationVar({ isActive: true, geometryType: tool, }); } }; };
改造完成后,你想要的写法可以直接通过类型校验,运行逻辑也完全正确:
{ id: '2', label: '', text: () => translate('MapAnnotation.Circle'), icon: 'circle', action: optionsActionConstructor(MenuType.DRAW, GeometryType.CIRCLE) }
方案2:使用bind预绑定参数
如果不想改造原函数的结构,可以用Function.prototype.bind预先填充参数,bind会返回一个新的函数引用,类型也能匹配要求:
{ id: '2', label: '', text: () => translate('MapAnnotation.Circle'), icon: 'circle', action: optionsActionConstructor.bind(null, MenuType.DRAW, GeometryType.CIRCLE) }
注意:该方案适合不依赖this上下文的函数,你的场景下函数没有用到this,可以正常使用;若TS对bind返回的函数类型推断不准,可以手动加类型断言为ActionType。
方案3:保留原有箭头函数包装
这是零改造成本、无任何隐式坑的写法,仅多了一层箭头函数包装,可读性和稳定性都有保障:
action: () => optionsActionConstructor(MenuType.DRAW, GeometryType.CIRCLE)
避坑提醒
不要为了通过类型校验直接给字段加as ActionType之类的强制类型断言,这种做法只是骗过了TS检查,运行时action拿到的还是void值,触发时必然报错。
内容的提问来源于stack exchange,提问作者Atl31
相关产品推荐
相关产品推荐

