Typescript React HOC与forwardRef键入问题

时间:2020-10-22 15:17:58

标签: reactjs typescript ref higher-order-components

我需要在React中使用forwardRef指定高阶组件的参数类型和返回类型。目前,我完成了以下实施。由于我尚未指定确切的ElementType,因此它可以工作,但并不完美。如果我尝试添加其他通用类型Element extends React.ElementType,则会发生此错误:

Error:(34, 10) TS2322: Type 'Pick<PropsWithChildren<withPermissionsProps & Props & ComponentProps<Element>>, "children" | Exclude<...> | Exclude<...>> & { ...; }' is not assignable to type 'IntrinsicAttributes & ComponentProps<Element> & Props & { children?: ReactNode; }'.
  Type 'Pick<PropsWithChildren<withPermissionsProps & Props & ComponentProps<Element>>, "children" | Exclude<...> | Exclude<...>> & { ...; }' is not assignable to type 'ComponentProps<Element>'.

如果我通过'div'对元素类型进行硬编码,则会出现以下错误:

Error:(32, 10) TS2769: No overload matches this call.
  Overload 1 of 2, '(props: ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & Props, context?: any): ReactElement<...> | ... 1 more ... | null', gave the following error.
    Type 'Pick<PropsWithChildren<withPermissionsProps & Props & ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement>>, "slot" | ... 255 more ... | Exclude<...>> & { ...; }' is not assignable to type 'IntrinsicAttributes & ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & Props'.
      Type 'Pick<PropsWithChildren<withPermissionsProps & Props & ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement>>, "slot" | ... 255 more ... | Exclude<...>> & { ...; }' is not assignable to type 'Props'.
        'Props' could be instantiated with an arbitrary type which could be unrelated to 'Pick<PropsWithChildren<withPermissionsProps & Props & ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement>>, "slot" | ... 255 more ... | Exclude<...>> & { ...; }'.
  Overload 2 of 2, '(props: PropsWithChildren<ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & Props>, context?: any): ReactElement<...> | ... 1 more ... | null', gave the following error.
    Type 'Pick<PropsWithChildren<withPermissionsProps & Props & ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement>>, "slot" | ... 255 more ... | Exclude<...>> & { ...; }' is not assignable to type 'IntrinsicAttributes & ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement> & Props & { ...; }'.
      Type 'Pick<PropsWithChildren<withPermissionsProps & Props & ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement>>, "slot" | ... 255 more ... | Exclude<...>> & { ...; }' is not assignable to type 'Props'.
        'Props' could be instantiated with an arbitrary type which could be unrelated to 'Pick<PropsWithChildren<withPermissionsProps & Props & ClassAttributes<HTMLDivElement> & HTMLAttributes<HTMLDivElement>>, "slot" | ... 255 more ... | Exclude<...>> & { ...; }'.
import PermissionDenied from '@/components/PermissionDenied'
import cn from 'classnames'
import React from 'react'

import style from './withPermissions.module.scss'

export interface withPermissionsProps {
  readable?: boolean
  executable?: boolean
  showPlaceholder?: boolean
}

export function withPermissions<Props>(
  Component: React.ComponentType<
    React.ComponentProps<React.ElementType> & Props
  >,
): React.ForwardRefExoticComponent<
  React.PropsWithoutRef<
    withPermissionsProps & Props & React.ComponentProps<React.ElementType>
  >
> {
  return React.forwardRef(function withPermissions_(
    {
      className,
      readable = false,
      executable = false,
      showPlaceholder = false,
      ...otherProps
    },
    ref,
  ) {
    return (
      ((readable || executable) && (
        <Component
          {...otherProps}
          ref={ref}
          className={cn(
            style.withPermissions,
            {
              [style.withPermissions_readonly]: readable && !executable,
              [style.withPermissions_executeOnly]: executable && !readable,
            },
            className,
          )}
        />
      )) ||
      (showPlaceholder && <PermissionDenied />) ||
      null
    )
  })
}

export default withPermissions

还要确保交叉点类型不包含我尝试省略的相同键,但这并没有帮助。

也许以前有人遇到过这个问题,我认为这是一件很普通的事情,必须先做一次,才不应该成为问题。

0 个答案:

没有答案