TypeScript中如何正确引用JSON结构中的变量字段名?
嘿,我来帮你搞定这个TypeScript的类型报错问题~首先得先指出你代码里的一个小笔误:你写的const label = ingredient1${i};会生成ingredient11、ingredient12、ingredient13这种不存在的字段名,应该改成ingredient${i}才对,不然就算解决了类型问题,也拿不到正确的食材值哦!
回到类型报错的核心问题:TypeScript之所以报错,是因为它没办法确定你动态生成的字符串label是DrinkResponseType类型里的合法键,所以默认把它当成了any类型。不用// @ts-ignore也有很多优雅的解决办法,下面给你几种常用方案:
方案一:把动态字段名断言为类型的合法键
你可以用as keyof DrinkResponseType告诉TypeScript,这个动态生成的字符串是DrinkResponseType的有效字段名,这样类型检查就会通过了:
export type DrinkResponseType = { id: string; name: string; ingredient1: string; ingredient2: string; ingredient3: string; } const drinks: Array<DrinkResponseType> = response.drinks; drinks.forEach((item: DrinkResponseType) => { let all_ingredients: Array<string> = []; for(let i=1;i<=3;i++){ // 修正笔误 + 类型断言 const label = `ingredient${i}` as keyof DrinkResponseType; const value = item[label]; if(value){ all_ingredients.push(value); } } console.log(all_ingredients); })
方案二:预先定义合法的字段名数组(更推荐)
这种方式更清晰,也能避免字符串拼接带来的错误,直接遍历预先声明好的食材字段名数组:
export type DrinkResponseType = { id: string; name: string; ingredient1: string; ingredient2: string; ingredient3: string; } const drinks: Array<DrinkResponseType> = response.drinks; // 预先定义所有食材字段的键 const ingredientKeys: Array<keyof DrinkResponseType> = ['ingredient1', 'ingredient2', 'ingredient3']; drinks.forEach((item: DrinkResponseType) => { let all_ingredients: Array<string> = []; ingredientKeys.forEach(key => { const value = item[key]; if(value){ all_ingredients.push(value); } }); console.log(all_ingredients); })
这种方案的好处是,如果以后要新增ingredient4,只需要在数组里加一个元素就行,而且TypeScript会帮你检查数组里的元素是不是合法的字段名,避免拼写错误。
方案三:给类型添加索引签名(灵活性高但不推荐)
如果你希望整个类型都支持字符串索引,可以给DrinkResponseType添加索引签名,但这样会牺牲一部分类型安全性——比如你可以用任意字符串去访问item的属性,TypeScript不会报错:
export type DrinkResponseType = { [key: string]: string; // 添加索引签名 id: string; name: string; ingredient1: string; ingredient2: string; ingredient3: string; } // 后面的代码就可以直接用动态字符串访问了 const drinks: Array<DrinkResponseType> = response.drinks; drinks.forEach((item: DrinkResponseType) => { let all_ingredients: Array<string> = []; for(let i=1;i<=3;i++){ const label = `ingredient${i}`; const value = item[label]; if(value){ all_ingredients.push(value); } } console.log(all_ingredients); })
一般不推荐这种方案,除非你确实需要非常灵活的字符串索引访问,否则前面两种方案更能保持TypeScript的类型优势。
备注:内容来源于stack exchange,提问作者oderfla

