ReactJS + TypeScript组件报错求助:Property 'height'不存在于Readonly<{}>
解决React TypeScript类组件中
Property 'height' does not exist on type 'Readonly<{}>'错误 这个报错的核心原因是TypeScript无法推断出你的组件state的结构,默认把state类型当成了空对象Readonly<{}>,所以当你访问this.state.base或this.state.height时,TS会认为这些属性不存在。下面是一步步的修复方案:
1. 定义State的类型接口
首先我们需要明确state的结构,创建一个接口来描述它:
interface TriangleState { base: number | undefined; height: number | undefined; area: number | undefined; error: string; }
然后在组件类中指定state的类型(同时把组件名改成首字母大写,符合React组件命名规范):
export default class TriangleArea extends React.Component<triangleInfo, TriangleState> { // ... }
2. 修复handleChange方法的逻辑
你的handleChange方法里错误地使用了name作为state的键,但你的input元素没有设置name属性,也没有区分是base还是height的输入。我们可以给input添加name属性(和state的字段名一致),然后动态更新对应的state:
handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { // 将输入的字符串转为数字,空值则设为undefined const value = event.target.value ? Number(event.target.value) : undefined; this.setState({ [event.target.name]: value } as Pick<TriangleState, 'base' | 'height'>); }
同时修改input元素,添加name属性并把类型改成number(限制用户输入非数字内容):
<input type="number" id="base" name="base" placeholder="base" value={this.state.base ?? ''} onChange={this.handleChange} /> <input type="number" id="height" name="height" placeholder="height" value={this.state.height ?? ''} onChange={this.handleChange} />
这里用?? ''处理undefined的情况,避免input出现"undefined"字符串。
3. 修复getArea方法的问题
- 给方法的参数指定类型:
React.FormEvent<HTMLFormElement> - 处理字符串转数字的问题(虽然input是number类型,但value依然是string,需要转成number)
- 给form添加
onSubmit绑定,触发getArea方法
修正后的getArea:
getArea = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); const base = Number(event.currentTarget.elements.base.value); const height = Number(event.currentTarget.elements.height.value); if (!isNaN(base) && base > 0 && !isNaN(height) && height > 0) { this.setState({ base, height, area: (base * height) / 2, error: "" }); } else { this.setState({ base: undefined, height: undefined, area: undefined, error: "Please enter positive numbers for base and height." }); } }
然后修改form标签,添加onSubmit:
<form onSubmit={this.getArea}>
完整修正后的代码
import React from 'react'; // 假设你的props类型是这样的,如果没有实际props可以改成{} interface triangleInfo {} interface TriangleState { base: number | undefined; height: number | undefined; area: number | undefined; error: string; } export default class TriangleArea extends React.Component<triangleInfo, TriangleState> { constructor(props: triangleInfo) { super(props); this.state = { base: undefined, height: undefined, area: undefined, error: "" }; } handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { const value = event.target.value ? Number(event.target.value) : undefined; this.setState({ [event.target.name]: value } as Pick<TriangleState, 'base' | 'height'>); } getArea = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); const base = Number(event.currentTarget.elements.base.value); const height = Number(event.currentTarget.elements.height.value); if (!isNaN(base) && base > 0 && !isNaN(height) && height > 0) { this.setState({ base, height, area: (base * height) / 2, error: "" }); } else { this.setState({ base: undefined, height: undefined, area: undefined, error: "Please enter positive numbers for base and height." }); } } render() { return ( <div> <form onSubmit={this.getArea}> <p>Calculate the area of a triangle!</p> <input type="number" id="base" name="base" placeholder="base" value={this.state.base ?? ''} onChange={this.handleChange} /> <input type="number" id="height" name="height" placeholder="height" value={this.state.height ?? ''} onChange={this.handleChange} /> <button type="submit">Get Area</button> </form> {this.state.area && <p>Triangle Area: {this.state.area}</p>} {this.state.error && <p style={{color: 'red'}}>{this.state.error}</p>} </div> ); } };
额外说明
- 组件名首字母大写是React的规范,避免和HTML标签冲突
- 使用
event.currentTarget而不是target,在表单提交时更可靠 - 添加了面积展示和错误提示的UI,提升用户体验
- 用
isNaN判断转换后的数字是否有效,避免非数字输入导致的计算错误
内容的提问来源于stack exchange,提问作者Daniel Isaac Chavez
相关产品推荐
相关产品推荐

