Typescript泛型重载下React高阶Mixin组件无自有属性类型推断问题
解决方案
你遇到的类型推断异常是TypeScript的React类型默认 fallback 逻辑导致的:当无法明确推断TOriginalProps为具体类型时,会默认回退到React内置的带可选children属性的PropsWithChildren类型,才会出现多余属性的问题。
不需要复杂的重载逻辑,调整泛型约束配合Omit工具类型即可同时兼容两种场景,代码如下:
import React from 'react'; export interface IExtraProps { extraProp: string; } export function MyMixin<TProps extends IExtraProps>( WrappedComponent: React.ComponentClass<TProps> ): React.ComponentClass<Omit<TProps, keyof IExtraProps>> { return class extends React.Component<Omit<TProps, keyof IExtraProps>> { public render() { const value = "something irrelevant to the question"; // 类型断言确保属性匹配 const props = {...this.props, extraProp: value} as TProps; return <WrappedComponent {...props} />; } } }
两种场景验证效果:
- 带自有属性的组件场景
// 假设自有属性定义 interface MyProps { id: number; name: string; } class MyComponent extends React.Component<MyProps & IExtraProps> {} // 推断返回类型为 React.ComponentClass<{id: number; name: string}>,符合预期 const WrappedMyComponent = MyMixin(MyComponent);
- 无自有属性的组件场景
class MyComponentNoProps extends React.Component<IExtraProps> {} // 推断返回类型为 React.ComponentClass<{}>,不会多出多余的children或extraProp属性,符合预期 const WrappedNoPropsComponent = MyMixin(MyComponentNoProps);
如果需要保留原有泛型结构使用重载,可以调整重载的泛型约束避免全匹配问题:
// 优先匹配无自有属性的场景 export function MyMixin(WrappedComponent: React.ComponentClass<IExtraProps>): React.ComponentClass<{}>; // 通用场景增加泛型约束,排除props正好等于IExtraProps的情况 export function MyMixin<TOriginalProps extends {}>(WrappedComponent: React.ComponentClass<TOriginalProps & IExtraProps>): React.ComponentClass<TOriginalProps>; // 实现和原有逻辑一致 export function MyMixin<TOriginalProps>(WrappedComponent: React.ComponentClass<TOriginalProps & IExtraProps>): React.ComponentClass<TOriginalProps> { return class extends React.Component<TOriginalProps> { public render() { const value = "something irrelevant to the question" const props = {...this.props, extraProp: value} return <WrappedComponent {...props} />; } } }
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

