dag*_*da1 5 typescript reactjs
这是代码:
type PropsWithChildren<P> = P & { children?: any };
interface FC<P = {}> {
(props: PropsWithChildren<P>, context?: any): any;
}
type BaseFields = {
label: string;
};
export type ComponentPropsType<C> = C extends FC<infer P> ? P : C;
export function renderFormControlDestructured<P extends PropsWithChildren<BaseFields>>(Comp: FC<P>) {
const Wrapped: FC<P> = ({ label, ...rest }) => {
return <Comp label={label} {...rest} />;
};
return Wrapped;
}
export function renderFormControlNotDestructured<P extends PropsWithChildren<BaseFields>>(Comp: FC<P>) {
const Wrapped: FC<P> = (props) => {
return <Comp {...props} label={props.label} />;
};
return Wrapped;
}
type SelectProps<OptionType> = {
options: OptionType[];
} & BaseFields;
const Select: FC<SelectProps<unknown>> = ({options}) => {
console.log(options)
}
const FormSelect1 = renderFormControlDestructured(Select);
const FormSelect2 = renderFormControlNotDestructured(Select);
console.log(FormSelect1, FormSelect2)
Run Code Online (Sandbox Code Playgroud)
我希望打字稿从传递的组件中推断出道具,但我收到以下错误消息
总而言之,如果我为这样的高阶组件解构我的论点
export function renderFormControlDestructured<P extends PropsWithChildren<BaseFields>>(Comp: FC<P>) {
const Wrapped: FC<P> = ({ label, ...rest }) => {
return <Comp label={label} {...rest} />;
};
return Wrapped;
}
Run Code Online (Sandbox Code Playgroud)
我收到错误消息:
Type '{ label: string; } & Pick<PropsWithChildren<P>, "children" | Exclude<keyof P, "label">>' is not assignable to type 'PropsWithChildren<P>'.
Type '{ label: string; } & Pick<PropsWithChildren<P>, "children" | Exclude<keyof P, "label">>' is not assignable to type 'P'.
'{ label: string; } & Pick<PropsWithChildren<P>, "children" | Exclude<keyof P, "label">>' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'PropsWithChildren<BaseFields>'.
Run Code Online (Sandbox Code Playgroud)
但是如果我不重组,我就不会收到错误
Type '{ label: string; } & Pick<PropsWithChildren<P>, "children" | Exclude<keyof P, "label">>' is not assignable to type 'PropsWithChildren<P>'.
Type '{ label: string; } & Pick<PropsWithChildren<P>, "children" | Exclude<keyof P, "label">>' is not assignable to type 'P'.
'{ label: string; } & Pick<PropsWithChildren<P>, "children" | Exclude<keyof P, "label">>' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'PropsWithChildren<BaseFields>'.
Run Code Online (Sandbox Code Playgroud)
我不明白为什么编译器允许一个而不是另一个实际上是相同的东西。
问题似乎出在解构上PropsWithChildren<P>。
export function renderFormControlDestructured<P extends PropsWithChildren<BaseFields>>(Comp: FC<P>) {
const Wrapped: FC<P> = ({ label, ...rest }) => {
return <Comp label={label} {...rest} />;
};
return Wrapped;
}
Run Code Online (Sandbox Code Playgroud)
这里rest的 类型Pick<PropsWithChildren<P>, "children" | Exclude<keyof P, "label">>与 不同PropsWithChildren<P>。
我们知道 type{ label: string; } & Pick<PropsWithChildren<P>, "children" | Exclude<keyof P, "label">>相当于PropsWithChildren<P>但它们显然是两种不同的类型。
如果我们FC在renderFormControlDestructured声明中扩展接口,我们将得到:
export function renderFormControlDestructured<P extends PropsWithChildren<BaseFields>>(Comp: (props: PropsWithChildren<P>, context?: any): any) {
const Wrapped: (props: PropsWithChildren<P>, context?: any): any = ({ label, ...rest }) => {
return <Comp label={label} {...rest} />;
};
return Wrapped;
}
Run Code Online (Sandbox Code Playgroud)
props类型也是如此PropsWithChildren<P extends PropsWithChildren<BaseFields>>,实际上,如果我们更改声明,PropsWithChildren从类型中删除嵌套的一个props:
function renderFormControlDestructured<P extends PropsWithChildren<BaseFields>>(Comp: FC<BaseFields>)
Run Code Online (Sandbox Code Playgroud)
错误消失。
多次嵌套PropsWithChildren实际上不会改变类型,第一次添加可选children属性,下一次用相同的属性替换该属性(实际上是一个noop);但似乎多个嵌套模板使得 TypeScript 很难重建类型。