【问题标题】:React & Typescript: Omitting a prop with spread syntax results in typescript error. Advanced typesReact 和 Typescript:省略带有扩展语法的 prop 会导致 typescript 错误。高级类型
【发布时间】:2021-08-31 12:15:38
【问题描述】:

我已经写下了这个高阶组件:

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&lt;PropsWithChildren&lt;P &amp; { isHidden: boolean; }&gt;, "children" | Exclude&lt;keyof P, "isHidden"&gt;&gt; 应该等于 PropsWithChildren&lt;P&gt;,因此它应该可以工作。任何想法为什么它不会?

【问题讨论】:

  • 听起来编译器的推断对类型感到困惑。我不知道这是否可行,但您可以尝试提供一些帮助:const { isHidden, ...passedProps }: { isHidden: boolean, passedProps: PropsWithChildren&lt;P&gt; } = props;。至少你可能会得到一个更有帮助的编译器错误,告诉你为什么不能转换传播变量。

标签: reactjs typescript typescript-generics react-typescript


【解决方案1】:

这个answer 详细解释了一般问题。如果你正在寻找这个问题的更扎实的例子,你可以寻找这个answer

我相信最清楚的解释是here

TS 不具备理解 Exclude & { [k]: T[k] } 等价于 T 所需的高阶推理能力。您只能通过理解什么 Exclude 来做出决定而 & 实际上在更高的层次上做,但从 TS 的角度来看,Exclude 只是一个类型别名

作为一种解决方案,您可能只是提示 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} /> 
    }
  }
}

playground link

【讨论】:

    猜你喜欢
    • 2020-09-12
    • 2018-03-01
    • 1970-01-01
    • 2020-10-08
    • 1970-01-01
    • 2019-06-28
    • 2018-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多