ESLint报错:类型MenuItemA | MenuItemB不存在属性'type'
解决TypeScript联合类型访问属性时的ESLint报错
在ESLint检查TypeScript代码时触发报错:Property 'type' does not exist on type MenuItemA | MenuItemB,代码运行正常,但lint阶段会抛出该错误。
代码示例
private menuPagesFiltered: (MenuItemA | MenuItemB )[] = [/* some data */] this.menuPagesFiltered.map(el => { if (el.type === 'wrapper') { // 报错位置 } }) export interface MenuItemA { title: string; open: boolean; type: 'wrapper'; } export interface MenuItemB { title: string; id?: string; url: string; icon: string; }
代码已简化
解决方案
1. 使用类型守卫缩小类型范围
通过in操作符判断属性是否存在,TypeScript会自动推断出对应的类型:
this.menuPagesFiltered.map(el => { if ('type' in el && el.type === 'wrapper') { // 此处el会被推断为MenuItemA类型 } })
也可以自定义类型谓词函数,更清晰地做类型判断:
function isMenuItemA(item: MenuItemA | MenuItemB): item is MenuItemA { return (item as MenuItemA).type === 'wrapper'; } this.menuPagesFiltered.map(el => { if (isMenuItemA(el)) { // 此处el确定为MenuItemA类型 } })
2. 给无type属性的接口添加标识
给MenuItemB添加一个可选的type属性并设为never,明确该接口不会有type属性,帮助TypeScript更准确地做类型推断:
export interface MenuItemB { title: string; id?: string; url: string; icon: string; type?: never; }
3. 类型断言(不推荐)
如果能确保当前元素一定是MenuItemA,可以用类型断言强制转换,但这种方式跳过了类型检查,存在安全风险:
this.menuPagesFiltered.map(el => { if ((el as MenuItemA).type === 'wrapper') { // 强制断言为MenuItemA类型 } })
原因说明
联合类型MenuItemA | MenuItemB中,只有MenuItemA包含type属性,TypeScript的严格类型检查(ESLint集成了该检查)要求必须确保访问的属性在所有联合类型成员上都存在,或者通过类型守卫缩小到存在该属性的子类型。代码运行时正常是因为JavaScript是弱类型语言,不会做静态类型检查。
内容的提问来源于stack exchange,提问作者Olehander Shevchuk
相关产品推荐
相关产品推荐

