最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Spread operator with React Props in Typescript (error: ...could be instantiated with a different subtype of constra

programmeradmin0浏览0评论

I am trying to write a Higher Order Component in React using Typescript that receives the props, 'consumes' one of them and then passes on the remainder to the Child ponent.

function testConnect<T>(Child: React.ComponentType<T>): React.ComponentType<T> {

  type InitialState = {
    iS: StoreShape.State;
  };

  type LAP = InitialState & T;

  const Connector = (props: LAP) => {
    const { iS, ...rest } = props;
    // do something with iS
    return (
      <Child // Visual Studio plains about this line.
        {...rest}
      />
    );
  };

  return Connector;
}

However this fails with the error: 'Pick<LAP, Exclude<keyof T, "iS">>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'

I would like to know not only if there's anything I can do about it, but also why this happens at all.

I am trying to write a Higher Order Component in React using Typescript that receives the props, 'consumes' one of them and then passes on the remainder to the Child ponent.

function testConnect<T>(Child: React.ComponentType<T>): React.ComponentType<T> {

  type InitialState = {
    iS: StoreShape.State;
  };

  type LAP = InitialState & T;

  const Connector = (props: LAP) => {
    const { iS, ...rest } = props;
    // do something with iS
    return (
      <Child // Visual Studio plains about this line.
        {...rest}
      />
    );
  };

  return Connector;
}

However this fails with the error: 'Pick<LAP, Exclude<keyof T, "iS">>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'

I would like to know not only if there's anything I can do about it, but also why this happens at all.

Share Improve this question edited Feb 25, 2020 at 23:14 AmerllicA 32.8k17 gold badges143 silver badges167 bronze badges asked Feb 21, 2020 at 17:28 AbulafiaAbulafia 1,76516 silver badges26 bronze badges 2
  • Actually, just pass {...props} on. – Jonas Wilms Commented Feb 21, 2020 at 17:50
  • Yeah, that's what I've acutally been doing. But I'd like to know what the solution is, or whether it's just a problem with React types - other experiements don't seem to have the same problem, but it could just be a plexity issue. – Abulafia Commented Feb 21, 2020 at 20:19
Add a ment  | 

2 Answers 2

Reset to default 6 +50

Actually, Typescript is catching a Problem with your ponent:

 const Component = testConnect(({ iS }) => <div>{iS}</div>);

 <Component iS={...} />

So you either have to

(a) pass on all props (instead of just rest) to the ponent.

   <Child   {...props} />

(b) Make sure that no prop named "iS" can be passed in by excluding the key iS from T:

 testConnect<T>(Child: React.ComponentType<Omit<T, "iS">>>): React.ComponentType<T> {

Here is a solution to your problem, not the most elegant one, but it stops to plain:

type InitialState = {
    iS: StoreShape.State;
};

function testConnect<T>(Child: React.ComponentType<T>): React.ComponentType<T> {
    const Connector = (props: InitialState & Exclude<T, "iS">) => {
        const isT = (object: any): object is T => {
            return !("iS" in object);
        };

        const { iS, ...rest } = props;

        if (isT(rest)) {
            return (
                <Child // Visual Studio plains on this line.
                    {...rest}
                />
            );
        }

        return <Child {...props} />;
    };

    return Connector;
}

To your code stops to plain, you need to fix how you are passing the props to the Child ponent. He accepts props of type T. But rest in your case is not of type T (or at least TS piler is not smart enough to figure it out), its type is Pick<LAP, Exclude<keyof T, "iS">> because of the rest operator you used.

My solution idea is just to let the piler knows that rest is of type T, using a custom type guard function, but you could use other approaches, like a type casting:

<Child
  {...((rest as unknown) as T)}
/>

I hope it helps you!

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论