React Navbar组件JS转TypeScript时三类TS报错修复咨询
报错1:TS2464 计算属性名类型错误
报错代码
setDropdown(state => ({ ...state, [name]: false }));
报错原因
你给name参数标注的类型是大写的String(JS包装对象类型),不符合TS计算属性名要求的string/number/symbol/any基础类型范围。
修复方法
将name的类型改为小写的TS基础类型string即可,你后续的更新已经处理了这个问题。
报错2:TS2683 this隐式具有any类型
报错代码
onMouseEnter={onMouseEnter.bind(this, 'settings')}
报错原因
函数式组件不存在类组件的实例this,使用bind绑定this本身不符合函数式组件的写法,TS识别到无类型声明的this就会抛出错误。
修复方法
你后续改成箭头函数传参的写法() => onMouseEnter('settings')是正确方案,无需绑定this就能正确传递参数,已经解决了该问题。
报错3:TS2322 元素上不存在class属性
报错代码
<i class='fab fa-firstdraft' />
报错原因
React为了避免和JS的class关键字冲突,规定所有HTML原生的class属性必须改用className属性,TS的类型检查会严格校验该规则。
修复方法
直接把class替换为className即可:
<i className='fab fa-firstdraft' />
优化后的完整可运行代码
额外给dropdown状态增加类型约束,避免后续写错键名导致的隐性问题:
import React, { useState } from 'react'; import { Button } from './Button'; import { Link } from 'react-router-dom'; import './Navbar.css'; import SettingsDropdown from "./SettingsDropdown"; import BillingDropdown from "./BillingDropdown"; // 定义dropdown状态的类型 type DropdownState = { settings: boolean; billing: boolean; } function Navbar() { const [click, setClick] = useState(false); // 给useState显式指定类型,强化类型检查 const [dropdown, setDropdown] = useState<DropdownState>({ settings: false, billing: false }); const handleClick = () => setClick(!click); const closeMobileMenu = () => setClick(false); // 用keyof限定name只能是dropdown的合法键名,避免传错参数 const onMouseEnter = (name: keyof DropdownState) => { if (window.innerWidth < 960) { setDropdown(state => ({ ...state, [name]: false })); } else { setDropdown(state => ({ ...state, [name]: true })); } }; const onMouseLeave = (name: keyof DropdownState) => { setDropdown(state => ({ ...state, [name]: false })); }; return ( <> <nav className='navbar'> <Link to='/' className='navbar-logo' onClick={closeMobileMenu}> Merchant Hub <i className='fab fa-firstdraft' /> </Link> <div className='menu-icon' onClick={handleClick}> <i className={click ? 'fas fa-times' : 'fas fa-bars'} /> </div> <ul className={click ? 'nav-menu active' : 'nav-menu'}> <li className='nav-item'> <Link to='/' className='nav-links' onClick={closeMobileMenu}> Home </Link> </li> <li className="nav-item" onMouseEnter={() => onMouseEnter('settings')} onMouseLeave={() => onMouseLeave('settings')} > <Link to="/settings" className="nav-links" onClick={closeMobileMenu} > Settings <i className="fas fa-caret-down" /> </Link> {dropdown.settings && <SettingsDropdown />} </li> <li className="nav-item" onMouseEnter={() => onMouseEnter('billing')} onMouseLeave={() => onMouseLeave('billing')} > <Link to="/billing" className="nav-links" onClick={closeMobileMenu}> Billing <i className="fas fa-caret-down" /> </Link> {dropdown.billing && <BillingDropdown />} </li> <li className='nav-item'> <Link to='/support' className='nav-links' onClick={closeMobileMenu} > Support </Link> </li> <li className='nav-item'> <Link to='/developers' className='nav-links' onClick={closeMobileMenu} > Developers </Link> </li> <li> <Link to='/sign-up' className='nav-links-mobile' onClick={closeMobileMenu} > Profile </Link> </li> </ul> <Button /> </nav> </> ); } export default Navbar;
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

