React自定义useFactory Hook:动态调整Props可选性
实现useFactory Hook的类型优化,满足预填Props后自动可选的需求
这个需求完全可以实现,通过自定义TypeScript辅助类型和调整泛型约束,就能让create函数自动识别已预填的必填Props,并将其转为可选,同时保留未预填的必填项要求。
核心思路
- 提取组件Props中的必填属性,明确哪些字段是必须提供的;
- 定义create函数的参数类型:移除已预填的属性,再将这些预填属性转为可选,确保未预填的必填属性仍保持必填要求;
- 利用TypeScript的泛型自动推断,让类型系统根据传入的预填Props自动调整create函数的参数约束。
完整实现代码
import React, { ComponentType } from 'react'; // 辅助类型:提取对象中的必填键 type RequiredKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? never : K; }[keyof T]; // 定义create函数的参数类型:已预填的属性转为可选,剩余必填属性保留必填 type FactoryCreateFn<P, T extends Partial<P>> = ( props: Omit<P, keyof T> & Partial<Pick<P, keyof T>> ) => JSX.Element; type UseFactoryProps<P, T extends Partial<P>> = { Component: ComponentType<P>; props?: T; }; const useFactory = <P, T extends Partial<P>>({ Component, props }: UseFactoryProps<P, T>): FactoryCreateFn<P, T> => { const create = (additionalProps) => { return <Component {...props} {...additionalProps} />; }; return create; }; // 测试组件 type MyComponentProps = { name: string; limit: number; message: string; delay?: number; color?: string; }; const MyComponent = (props: MyComponentProps) => { return <div>{props.name} - {props.limit} - {props.message}</div>; };
使用示例
// 预填name和limit const createMyComponent = useFactory({ Component: MyComponent, props: { name: "默认名称", limit: 20 } }); // 合法:仅传入剩余必填项message const Component1 = createMyComponent({ message: "测试消息" }); // 合法:传入message+可选属性color,同时覆盖预填的name const Component2 = createMyComponent({ message: "覆盖测试", color: "#ff0000", name: "新名称" }); // 报错:缺少必填的message // const Component3 = createMyComponent({ color: "#00ff00" });
类型逻辑说明
RequiredKeys<T>:遍历对象属性,判断哪些属性是必填的(即去掉该属性后,对象不再是原类型的子集),返回这些属性的键名联合类型;FactoryCreateFn<P, T>:通过Omit<P, keyof T>移除已预填的属性,再通过Partial<Pick<P, keyof T>>将这些预填属性转为可选,最终合并后的类型既保证了未预填的必填项必须传入,又允许覆盖或补充预填属性;- 泛型自动推断:调用
useFactory时,TypeScript会根据传入的props自动推断出T的类型,无需手动指定,让类型约束更智能。
内容的提问来源于stack exchange,提问作者Andyally
相关产品推荐
相关产品推荐

