TypeScript 中 React 组件 Props 的联合类型智能推导需用可辨识联合(type 字面量字段)+ 泛型约束 + 条件类型;如 ButtonProps 以 type 区分,配合 as const 和 Extract 可实现精准类型缩小与 IDE 补全。
在 TypeScript 中为 React 组件的 Props 实现联合类型(union type)下的智能类型推导,关键在于利用 discriminated union(可辨识联合) + 泛型约束 + 条件类型,让编辑器(如 VS Code)能根据某个公共字段(如 type)自动缩小 props 的具体类型,并给出精准的补全与校验。
这是最常用也最可靠的方式。确保联合类型的每个成员都有一个字面量类型(literal type)的公共字段,且值互不相同:
type ButtonProps =| { type: 'primary'; size?: 'sm' | 'md' | 'lg'; onClick: () => void }| { type: 'link'; href: string; target?: string }| { type: 'icon'; icon: string; ariaLabel: string };当组件接收 { type: 'link', href: '/home' } 时,TypeScript 会自动推导出完整类型是 { type: 'link'; href: string; target?: string },IDE 就能提示 href 必填、onClick 不可用等。
如果 props 来自字面量对象(比如直接传入 JSX),默认可能被宽泛推导为 string。加 as const 可保留字面量类型:
<Button type="link" // ✅ 推导为 'link'(而非 string)href="/login" />
更进一步,可在组件定义中用泛型约束确保 type 是已知字面量:
function Button<T extends ButtonProps['type']>(props: Extract<ButtonProps, { type: T }>) {// props 类型随 T 精确变化}当需要根据 type 自动推导对应事件处理器或子组件结构时,可用条件类型提取:
type EventHandler<T> = T extends 'primary'? { onClick: () => void }: T extends 'link'? { onClick?: () => void; onHover?: () => void }: { onIconClick?: () => void };type SmartButtonProps<T extends string = string> = T extends ButtonProps['type']? { type: T } & EventHandler<T> & Omit<Extract<ButtonProps, { type: T }>, 'type'>: never;这样 <Button type="primary" onClick={() => {}} /> 的 onClick 就不会被误标为可选,也能防止传入 href 这类非法字段。
string 或 any 做 discriminant 字段(如 { kind: string }),否则联合无法被区分type 字段的字面量标注(如写成 type: string),应始终是 type: 'primary'
React.forwardRef 或 React.memo,需显式标注泛型参数,否则类型可能丢失"strict": true 和 "exactOptionalPropertyTypes": true(推荐开启)