React & Typescript:省略带有扩展语法的 prop 会导致 typescript 错误。高级类型
React & Typescript: Omitting a prop with spread syntax results in typescript error. Advanced types
我记下了这个高阶组件:
type WrappedComponentConditionallyHidden =
<P>(WrappedComponent: React.ComponentType<P>) => React.FC<P & { isHidden: boolean }>;
const hideConditional: WrappedComponentConditionallyHidden = (WrappedComponent) => {
return (props) => {
// typeof props is inferred here correctly: P & { isHidden: boolean }
// Don't want to pass down "isHidden"
const { isHidden, ...passedProps } = props;
if (props.isHidden) {
return null;
} else {
return <WrappedComponent {...passedProps} />
// Passing { ...props } works but ^^^^ this fails
}
}
}
我收到这个 Typescript 错误:
Type 'Pick<PropsWithChildren<P & { isHidden: boolean; }>, "children" | Exclude<keyof P, "isHidden">>' is not assignable to type 'IntrinsicAttributes & P & { children?: ReactNode; }'
Type 'Pick<PropsWithChildren<P & { isHidden: boolean; }>, "children" | Exclude<keyof P, "isHidden">>' is not assignable to type 'P'.
'Pick<PropsWithChildren<P & { isHidden: boolean; }>, "children" | Exclude<keyof P, "isHidden">>' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint '{}'.
对我来说,'Pick<PropsWithChildren<P & { isHidden: boolean; }>, "children" | Exclude<keyof P, "isHidden">>
应该等于 PropsWithChildren<P>
,因此它应该有效。知道为什么它不会吗?
这个answer. And if you're looking for more grounded example of this problem you may look for this .
中对一般问题进行了非常详细的解释
我相信最清楚的解释已经完成here:
TS isn't capable of the higher-order reasoning needed to understand that Exclude<T, k> & { [k]: T[k] } is equivalent to T. You can only make that determination through understanding what Exclude and & actually do at a higher level, but from TS's point of view, Exclude is just a type alias
作为解决方案,您可能只是向 TS 提示 passedProps
:
的真实类型
const hideConditional = function <P>(WrappedComponent: React.ComponentType<P>): React.FC<P & { isHidden: boolean }> {
return (props) => {
const { isHidden, ...passedProps } = props;
if (props.isHidden) {
return null;
} else {
return <WrappedComponent {...passedProps as P} />
}
}
}
我记下了这个高阶组件:
type WrappedComponentConditionallyHidden =
<P>(WrappedComponent: React.ComponentType<P>) => React.FC<P & { isHidden: boolean }>;
const hideConditional: WrappedComponentConditionallyHidden = (WrappedComponent) => {
return (props) => {
// typeof props is inferred here correctly: P & { isHidden: boolean }
// Don't want to pass down "isHidden"
const { isHidden, ...passedProps } = props;
if (props.isHidden) {
return null;
} else {
return <WrappedComponent {...passedProps} />
// Passing { ...props } works but ^^^^ this fails
}
}
}
我收到这个 Typescript 错误:
Type 'Pick<PropsWithChildren<P & { isHidden: boolean; }>, "children" | Exclude<keyof P, "isHidden">>' is not assignable to type 'IntrinsicAttributes & P & { children?: ReactNode; }'
Type 'Pick<PropsWithChildren<P & { isHidden: boolean; }>, "children" | Exclude<keyof P, "isHidden">>' is not assignable to type 'P'.
'Pick<PropsWithChildren<P & { isHidden: boolean; }>, "children" | Exclude<keyof P, "isHidden">>' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint '{}'.
对我来说,'Pick<PropsWithChildren<P & { isHidden: boolean; }>, "children" | Exclude<keyof P, "isHidden">>
应该等于 PropsWithChildren<P>
,因此它应该有效。知道为什么它不会吗?
这个answer. And if you're looking for more grounded example of this problem you may look for this
我相信最清楚的解释已经完成here:
TS isn't capable of the higher-order reasoning needed to understand that Exclude<T, k> & { [k]: T[k] } is equivalent to T. You can only make that determination through understanding what Exclude and & actually do at a higher level, but from TS's point of view, Exclude is just a type alias
作为解决方案,您可能只是向 TS 提示 passedProps
:
const hideConditional = function <P>(WrappedComponent: React.ComponentType<P>): React.FC<P & { isHidden: boolean }> {
return (props) => {
const { isHidden, ...passedProps } = props;
if (props.isHidden) {
return null;
} else {
return <WrappedComponent {...passedProps as P} />
}
}
}