将 React 属性从属性值转换为子元素
像处理HTML属性一样传递数据,在TypeScript中定义类型属性,安全地进行解构,并将属性设为只读。
使用 TypeScript 处理 React 属性(2026 版入门指南)
在针对 React 19.2 及兼容编译器的 TypeScript 所推出的“重启 React”系列文章中,早期的 ProductCard 存在一个缺陷:产品相关字段都位于组件内部。而重用组件则需要通过属性来传递数据,这些数据就如同 HTML 属性一样从父组件传入。
像处理属性一样传递参数
function ProductCard() {
const product = { name: 'Mechanical Keyboard', price: 89000 }; // fixed
return <h2>{product.name}</h2>;
}
// receiving side
function ProductCard(props) {
return <h2>{props.name}</h2>;
}
数据由父组件持有,子组件则负责将其渲染出来。
为参数添加类型定义
为属性对象定义一个接口(或类型):
// passing side
<ProductCard name="Mechanical Keyboard" />
<ProductCard name="Wireless Mouse" />
type ProductCardProps = {
name: string;
price: number;
};
这样编译器就能在运行前检测到缺失的字段或错误的类型。
通过解构提升可读性
function ProductCard(props: ProductCardProps) {
return (
<div className="card">
<h2>{props.name}</h2>
<p>{props.price.toLocaleString()} won</p>
</div>
);
}
<ProductCard name="Keyboard" price={89000} /> // ✅ OK
<ProductCard name="Keyboard" /> // 🔴 missing price — error
<ProductCard name="Keyboard" price="89000" /> // 🔴 price is a string — error
将参数类型直接写在函数参数上,这样解构操作也能保持类型安全。
可选参数与默认值
type ProductCardProps = {
name: string;
price: number;
};
// drop the props. and pull values out directly
function ProductCard({ name, price }: ProductCardProps) {
return (
<div className="card">
<h2>{name}</h2>
<p>{price.toLocaleString()} won</p>
</div>
);
}
用?标记可选字段,并通过解构或默认参数提供默认值。
children
标签之间的内容会作为子元素出现:
type ProductCardProps = {
name: string;
price: number;
discount?: number; // may or may not be present
};
function ProductCard({ name, price, discount = 0 }: ProductCardProps) {
const finalPrice = price - discount;
return (
<div className="card">
<h2>{name}</h2>
<p>{finalPrice.toLocaleString()} won</p>
</div>
);
}
除非需要更严格的类型约束,否则将children定义为React.ReactNode。
在DevTools中查看
// both are valid
<ProductCard name="Keyboard" price={89000} /> // discount is 0
<ProductCard name="Mouse" price={45000} discount={5000} />
检查组件树以确认实际传入了哪些属性——在调试封装组件时非常有用。
属性为只读
type CardProps = {
children: React.ReactNode;
};
function Card({ children }: CardProps) {
return <div className="card">{children}</div>;
}// everything between the tags goes in as children
<Card>
<h2>Mechanical Keyboard</h2>
<p>89,000 won</p>
</Card>
绝不要在子组件内部修改属性。如果子组件需要更改状态,应提升状态或传递设置器回调函数。
总结
function ProductCard({ name, price }: ProductCardProps) {
price = price * 2; // 🔴 absolutely forbidden — trying to change props directly
return <p>{price} won</p>;
}
结合属性与TypeScript,可以实现具有编译时类型约束的可复用UI。本系列后续内容通常会涉及状态管理、副作用处理以及数据获取——每层依然都会保持类型约束。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖单仓库结构即可将其粘贴到沙箱中。
建议使用较小的示例,这样读者无需依赖 monorepo 即可将其粘贴到沙箱环境中。
建议使用较小的示例,这样读者无需依赖 monorepo 即可将其粘贴到沙箱环境中。
建议使用较小的示例,这样读者无需依赖 monorepo 即可将其粘贴到沙箱环境中。
建议使用较小的示例,这样读者无需依赖 monorepo 即可将其粘贴到沙箱环境中。