如何用TypeScript和React实现基于组件的智能属性类型推导?
实现Alert组件actions的自动类型推导
需求说明
我有一个Alert组件,包含可点击的操作项,这些操作项可以使用Button或Link等不同组件。希望实现以下效果:
<Alert actions={[{ component: Link, props: { /* 仅允许传入Link的属性 */ } }]} />
以及
<Alert actions={[{ component: Button, props: { /* 仅允许传入Button的属性 */ } }]} />
即props的类型能根据component属性自动确定,无需手动添加<Alert<ButtonProps> ... />这类额外泛型,实现类型的自动智能推导。
可行方案(TypeScript实现)
完全可以实现,核心是利用TypeScript的ComponentProps工具类型和泛型数组的自动推断能力,以下是具体实现代码:
1. 基础组件类型定义(示例)
先假设我们有Button和Link组件的类型(如果是第三方库如React Router的Link,直接用其类型即可):
import React from 'react'; // 自定义Button组件类型 type ButtonProps = { onClick: () => void; children: React.ReactNode; variant?: 'primary' | 'secondary'; }; const Button = ({ onClick, children, variant = 'primary' }: ButtonProps) => ( <button onClick={onClick} className={`btn btn-${variant}`}>{children}</button> ); // 自定义Link组件类型(或React Router的Link) type LinkProps = { to: string; children: React.ReactNode; target?: '_blank'; }; const Link = ({ to, children, target }: LinkProps) => ( <a href={to} target={target} className="link">{children}</a> );
2. Alert组件的类型与实现
import React from 'react'; import type { ComponentType, ComponentProps } from 'react'; // 定义单个操作项的类型:泛型C表示组件类型,props自动匹配该组件的属性 type ActionItem<C extends ComponentType<any>> = { component: C; props: ComponentProps<C>; }; // Alert组件的Props类型:actions是一个由不同ActionItem组成的数组 type AlertProps = { message: string; actions?: Array<ActionItem<ComponentType<any>>>; }; // Alert组件实现 const Alert = ({ message, actions = [] }: AlertProps) => ( <div className="alert"> <p>{message}</p> <div className="alert-actions"> {actions.map(({ component: Comp, props }, index) => ( <Comp key={index} {...props} /> ))} </div> </div> );
3. 使用示例(自动类型推导生效)
此时使用Alert组件时,TypeScript会自动根据component的值推断props的类型:
// 传入Link组件时,props只能传入LinkProps的属性 <Alert message="请确认操作" actions={[ { component: Link, props: { to: '/confirm', children: '确认', // 这里如果传入onClick(不属于LinkProps)会直接报错 } } ]} /> // 传入Button组件时,props只能传入ButtonProps的属性 <Alert message="操作成功" actions={[ { component: Button, props: { onClick: () => console.log('关闭'), children: '关闭', variant: 'secondary' // 这里如果传入to(不属于ButtonProps)会直接报错 } } ]} />
原理说明
- 利用
ComponentProps<C>工具类型,可以直接获取任意React组件C的属性类型; - 通过将
ActionItem定义为带泛型的类型,让TypeScript在解析actions数组时,自动为每个元素匹配component对应的props类型; - 无需手动为Alert组件指定泛型参数,完全由TypeScript自动推断,达到“智能推导”的效果。
内容的提问来源于stack exchange,提问作者Sheppard25
相关产品推荐
相关产品推荐

