React+TypeScript遍历对象输出分类名时map报错如何解决
问题背景
开发目标是列出所有分类的键名,示例数据中对应prospecting、estimate两个分类。
待遍历的数据源结构如下:
{ "categories": { "prospecting": { "name": "Nos offres", "products": { "product1": { "service": "Le pack", "title": "Le pack", "description": "Un accompagnement unique à 360° au service de votre performance. erat nibh, tristique quis augue ac, egestas porttitor mauris-", "redirect": "/accueil" }, "product2": { "service": "Nouveauté", "title": "Le pack 2", "description": "Vestibulum erat nibh, tristique quis augue ac, egestas porttitor mauris-", "redirect": "/accueil" } } }, "estimate": { "name": "Nos offres", "products": { "product1": { "service": "Le pack", "title": "Le pack", "description": "Un accompagnement unique à 360° au service de votre performance. erat nibh, tristique quis augue ac, egestas porttitor mauris-", "redirect": "/accueil" }, "product2": { "service": "Nouveauté", "title": "Le pack 2", "description": "Vestibulum erat nibh, tristique quis augue ac, egestas porttitor mauris-", "redirect": "/accueil" } } } } }
原有实现代码:
export default function Filters(props: any) { const [listOfCategories, setListOfCategories] = useState() useEffect(() => { const listOfCategories = props.categories.map(category => { setListOfCategories(category) }) console.log(listOfCategories) })
运行时VSCode对map方法内的category参数标红,报错信息:Parameter 'category' implicitly has an 'any' type
报错原因
两个核心问题导致报错和逻辑错误:
- 遍历方法用错:
map是数组专属的遍历方法,而props.categories是键值对结构的普通对象,本身不存在map方法,直接调用本身逻辑就不成立。 - 类型定义缺失:你给组件props直接标注了
any类型,TS无法推断categories内部的结构,同时遍历参数也没有明确类型,就会触发「参数隐式为any类型」的校验报错。另外现有代码还存在useState无初始值、useEffect无依赖数组、循环内重复调用setState触发多余重渲染的问题。
修复方案
- 首先定义明确的TS类型,替换掉
any的松散类型标注,从根源避免类型报错:
// 定义单条产品的类型 type Product = { service: string title: string description: string redirect: string } // 定义单个分类的类型 type Category = { name: string products: Record<string, Product> } // 定义组件接收的props类型 type FiltersProps = { categories: Record<string, Category> }
- 用JS原生对象遍历方法拿到分类键名:要获取普通对象的所有键名,用
Object.keys()即可,该方法会返回对象所有可枚举键名组成的数组,之后就能正常调用数组方法遍历。 - 修正后的完整可运行代码:
import { useState, useEffect } from 'react' type Product = { service: string title: string description: string redirect: string } type Category = { name: string products: Record<string, Product> } type FiltersProps = { categories: Record<string, Category> } export default function Filters(props: FiltersProps) { // 给useState传泛型和初始值,明确存储的是字符串数组(分类键名) const [listOfCategories, setListOfCategories] = useState<string[]>([]) useEffect(() => { // 拿到所有分类键名组成的数组:['prospecting', 'estimate'] const categoryKeys = Object.keys(props.categories) // 一次性更新状态,不要在循环里反复调用set方法 setListOfCategories(categoryKeys) console.log(categoryKeys) // 传入依赖数组,只有categories变化时才重新执行副作用 }, [props.categories]) return ( <div className="category-list"> {/* 渲染分类列表示例 */} {listOfCategories.map(categoryKey => ( <div key={categoryKey}>{categoryKey}</div> ))} </div> ) }
额外拓展
如果你后续遍历的时候不仅需要分类键名,还需要对应分类的内容,可以用Object.entries()方法,它会返回[键名, 对应值]格式的数组,使用更灵活:
useEffect(() => { const categoryEntries = Object.entries(props.categories) categoryEntries.forEach(([key, categoryDetail]) => { console.log('分类键名:', key) console.log('分类名称:', categoryDetail.name) }) }, [props.categories])
日常写TS尽量不要用any类型,提前定义好数据结构,就能避免绝大多数隐式类型报错。
内容的提问来源于stack exchange,提问作者Johan
相关产品推荐
相关产品推荐

