元素隐式具有 “any“ 类型,因为类型为 “string“ 的表达式不能用于索引类型 类型“Object”上不存在属性xxx 类型 “xxx“ 到类型 “xxx“ 的转换可能是错误

文章讲述了在使用TypeScript时遇到的类型报错问题,主要是由于对象的动态属性访问引起的。作者首先介绍了问题的数据结构,然后详细描述了尝试解决报错的三个步骤,包括使用any类型、定义接口和使用unknown类型。最终,作者提供了两种可行的解决方案来正确地访问和操作对象的深层结构。

全部报错

  1. 元素隐式具有 “any” 类型,因为类型为 “string” 的表达式不能用于索引类型

  2. 类型“Object”上不存在属性xxx

  3. 类型 “xxx” 到类型 “xxx” 的转换可能是错误的,因为两种类型不能充分重叠。如果这是有意的,请先将表达式转换为 “unknown”

数据结构

  const data = {
    "spleen": {
        organ: '脾脏',
        organ_Eng: 'spleen',
        x: {
            diameter: [2, 3, 4],
            area: [1, 2, 3]
        },
        y: {
            diameter: [2, 3, 4],
            area: [1, 2, 3]
        },
        z: {
            diameter: [2, 3, 4],
            area: [1, 2, 3]
        }
    },
    "rightKidney": {
        organ: '右肾',
        organ_Eng: 'rightKidney',
        x: {
            diameter: [2, 3, 4],
            area: [1, 2, 3]
        },
        y: {
            diameter: [2, 3, 4],
            area: [1, 2, 3]
        },
        z: {
            diameter: [2, 3, 4],
            area: [1, 2, 3]
        }
    },
  }

目的

我想要访问这个对象最里层的结构,除了diameter以及area之外,其他的都需要通过变量去访问
现有变量如下:

const config = {
        organ: 'spleen',
        axis: 'x',
        slice: 3,
    }

我想要用类似于以下的这种方式来进行访问

const organData = data[config.organ]; // 当前器官
const axisData = organData[config.axis] // 当前坐标轴
const slice = config.slice // 当前切片

第一个报错

报错了,报错长这个样子:

元素隐式具有 “any” 类型,因为类型为 “string” 的表达式不能用于索引类型
找不到具有类型为 “string” 的参数的索引签名

对于这个问题,第一个解决方法是给对象加一个类型的声明,代码是这样的:

interface dataObj {
    [organ: string]: any
};

  const data = {
    "spleen": {
		// ...
    },
    "rightKidney": {
    	// ...
    },
  } as dataObj 

为什么要写any呢?写any的话ts的作用不就没有了吗?那就不写any吧,从Object开始进行尝试,像以下这样使用的时候报错了

const options = Object.values(data).map((value)=>{
    return {value: value.organ_Eng, label: value.organ}
});

第二个报错

报错了,报错长这个样子

类型“Object”上不存在属性“organ_Eng”

分析一下这个报错,它的意思就是我得把整个对象里面各种元素的类型给写出来,写就写呗,然后我就把类型定义弄成这样了

type axisObj = {
    diameter: number[],
    area: number[],
}

interface dataObj {
    [organ: string]: {
        organ: string,
        organ_Eng: string,
        x: axisObj,
        y: axisObj,
        z: axisObj,
    }
};

然后在以下的代码中出现了新的报错:

const axisData = organData[axis]

报错:
元素隐式具有 “any” 类型,因为类型为 “string” 的表达式不能用于索引类型
在类型 上找不到具有类型为 “string” 的参数的索引签名。

好像又回到了起点。。。,分析一下,大概就是跟一开始的报错是一个意思,没有声明不能随便用,那行呗,加个声明。
然后我又在以上的代码的基础上将代码修改成这样:

interface organObj {
    [axis: string]: axisObj,
}

const organData = data[config.organ] as organObj; // 当前器官

第三个报错

新的报错出现了,长这个样子:

类型 “{ organ: string; organ_Eng: string; x: axisObj; y: axisObj; z: axisObj; }” 到类型 “organObj” 的转换可能是错误的,因为两种类型不能充分重叠。如果这是有意的,请先将表达式转换为 “unknown”。
属性“organ”与索引签名不兼容。
类型“string”不可与类型“axisObj”进行比较

既然让我们加unknown,那就加上试一试,代码变成这样了:

const organData = data[config.organ] as unknown as organObj; // 当前器官

报错没有了,皆大欢喜。

总结

所以有以下的两种解决方法,详细的代码我都放出来:

相同的部分

  const data = {
    "spleen": {
		// ...
    },
    "rightKidney": {
		// ...
    },
  }  as dataObj

const config = {
        organ: 'spleen',
        axis: 'x',
        slice: 3,
    }

第一种解决方案

interface dataObj {
    [organ: string]: any
};

const organData = data[config.organ]; // 当前器官
const axisData = organData[config.axis] // 当前坐标轴
const slice = config.slice // 当前切片

第二种解决方案

type axisObj = {
    diameter: number[],
    area: number[],
}

interface organObj {
    [axis: string]: axisObj,
}

interface dataObj {
    [organ: string]: {
        organ: string,
        organ_Eng: string,
        x: axisObj,
        y: axisObj,
        z: axisObj,
    }
};

const organData = data[config.organ] as unknown as organObj; // 当前器官
const axisData = organData[config.axis] // 当前坐标轴
const slice = config.slice // 当前切片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值