React + TypeScript 实现带子项判断的无序列表时遇到报错及功能疑问
嗨,我来帮你捋清楚这两个问题的根源,以及为什么在JS里正常、TS里出问题~
首先说你遇到的**「expression expected」语法错误**,这是最直接的导火索:你写的map箭头函数用了{}包裹逻辑代码,但最后没给这个块级作用域加闭合的}!解析器找不到对应的结束大括号,就会直接报"表达式期望"的错误,而且因为语法解析混乱,还顺带误判了detail参数没被使用——其实你明明用了detail,只是语法错误导致TS没正确识别到。
看你原代码的结尾部分:
}else{ return <li>{detail}</li> }) } </ul>
这里箭头函数的{只开了没关,要在else的return后面补一个},改成这样才对:
}else{ return <li>{detail}</li> })} </ul>
然后是为什么JS里正常、TS里不行的问题:
严格来说,如果你在JS里写了同样有语法错误的代码,也会报错!大概率是你在JS里用的是「隐式返回」的写法(箭头函数不用{},直接写返回表达式),比如:
c.details.map(detail => detail.slice(0,2) === "--" ? <ul><li>{detail}</li></ul> : <li>{detail}</li>)
这种写法不需要return也不需要块级作用域{},语法是完全正确的,所以JS能正常运行。但你转到TS的时候改成了带{}的块级作用域写法,却漏了闭合的},才导致了语法错误。
另外,TS作为类型严格的语言,还需要你给数据定义明确的类型,不然它没法推断c.details是字符串数组,也可能带来隐性错误。比如你可以给c对应的结构定义接口:
// 定义数据结构的类型 interface ListData { details: string[]; // 这里可以加c的其他属性 } // 模拟你的数据,指定类型 const c: ListData = { details: ["主条目1", "--子条目1-1", "主条目2", "--子条目2-1"], };
如果c是从组件props传进来的,也要在组件的Props接口里定义好:
interface MyComponentProps { c: ListData; } const MyList = (props: MyComponentProps) => { // 组件逻辑 };
最后给你一个修正后的完整TSX示例,还顺便加了React要求的key属性(这个不管JS还是TS都应该加,避免渲染警告),以及可选的子项前缀移除逻辑:
import React from 'react'; interface ListData { details: string[]; } const NestedList = () => { const c: ListData = { details: ["主项1", "--子项1-1", "主项2", "--子项2-1", "--子项2-2"], }; return ( <ul> {c.details.map((detail, index) => { if (detail.slice(0, 2) === "--") { // 移除子项的--前缀,可选操作 const subItemText = detail.replace(/^--/, ''); return ( <ul key={index}> <li>{subItemText}</li> </ul> ); } else { return <li key={index}>{detail}</li>; } })} </ul> ); }; export default NestedList;
如果觉得块级作用域写法麻烦,也可以用三元表达式的隐式返回写法,更简洁:
<ul> {c.details.map((detail, index) => detail.slice(0,2) === "--" ? ( <ul key={index}> <li>{detail.replace(/^--/, '')}</li> </ul> ) : ( <li key={index}>{detail}</li> ) )} </ul>
内容来源于stack exchange

