省略部分类型,以将该类型分为两部分

时间:2019-05-16 17:52:59

标签: reactjs typescript

我正在尝试制作一个extendProps函数,该函数将:

  • 获取一个React组件及其部分道具
  • 返回一个新的React组件,该组件不需要已经提供的那些道具

示例

type Props = { first: string; second: string; third: string };

const ExampleComponent = ({ first, second, third }: Props) => (
  <div>
    <span>{first}</span>
    <span>{second}</span>
    <span>{third}</span>
  </div>
);

// Sets the "first" prop to "FIRST"
const ExtendedComponent = extendProps(ExampleComponent, {first: 'FIRST'});
<ExtendedComponent second="SECOND" third="THIRD" />;

使用泛型进行这项工作非常棘手,我想知道自己在做错什么。

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

function extendProps<P extends object, E extends Partial<P>>(
  Component: React.ComponentType<P>,
  extendedProps: E,
) {
  return (remainingProps: Omit<P, keyof E>) =>
    <Component {...remainingProps} {...extendedProps} />;
}

我遇到很多错误:


App.tsx:35:35 - error TS2344: Type 'keyof E' does not satisfy the constraint 'keyof P'.
  Type 'string | number | symbol' is not assignable to type 'keyof P'.
    Type 'string' is not assignable to type 'keyof P'.
      Type 'string' is not assignable to type 'never'.
        Type 'keyof E' is not assignable to type 'never'.
          Type 'string | number | symbol' is not assignable to type 'never'.
            Type 'string' is not assignable to type 'never'.

35   return (remainingProps: Omit<P, keyof E>) => <Component {...remainingProps} {...extendedProps} />;
                                     ~~~~~~~

App.tsx:35:49 - error TS2322: Type 'E' is not assignable to type 'IntrinsicAttributes & P & { children?: ReactNode; }'.
  Type 'Partial<P>' is not assignable to type 'IntrinsicAttributes & P & { children?: ReactNode; }'.
    Type 'Partial<P>' is not assignable to type 'P'.
      Type 'E' is not assignable to type 'P'.
        Type 'Partial<P>' is not assignable to type 'P'.

35   return (remainingProps: Omit<P, keyof E>) => <Component {...remainingProps} {...extendedProps} />;
                                                   ~~~~~~~~~


Found 2 errors.

Here is a playground link。 (必须制作一些模拟类型才能使其在其中运行)

1 个答案:

答案 0 :(得分:1)

type ReactComponentType<P> = (props: P) => null;
type Component<P> = (props: P) => null
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

function extendProps<P extends Record<string | number | symbol, any>, E extends Partial<P>>(
  Component: ReactComponentType<P>,
  extendedProps: E,
) {
  return (remainingProps: Omit<P, keyof E>) => Component( {...remainingProps, ...extendedProps} as P);
}

type Props = { first: string; second: string; third: string };

const ExampleComponent = ({ first, second, third }: Props) => null

// Sets the "first" prop to "FIRST"
const ExtendedComponent = extendProps(ExampleComponent, {first: 'FIRST'});
ExtendedComponent({ second: 'SECOND', third: 'THIRD' })