9

I'm trying to create an asyncComponent higher order component with TypeScript, but can't quite get the types right.

Essentially, this works in JS with webpack...

const Auth = asyncComponent(() =>
  require.ensure([], require => require("../auth/index").default, "auth_async"),
);

My asyncComponent is a higher order function that does the following...

import * as React from "react";
import { Component } from 'react';

export interface IAsyncComponentProps {}

export interface IAsyncComponentState {
  Component: typeof Component
}

interface IGetComponent {
  (): Promise<typeof Component>;
}

export default function asyncComponent (getComponent: IGetComponent) {
  let ComponentCache: typeof Component = null;

  return class AsyncComponent extends Component<IAsyncComponentProps, IAsyncComponentState> {
    state: {
      Component: typeof Component,
    };

    constructor(props: IAsyncComponentProps) {
      super(props);
      this.state = { Component: ComponentCache };
    }

    componentWillMount() {
      if (!this.state.Component) {
        getComponent().then((Component) => {
          ComponentCache = Component;

          this.setState({ Component });
        });
      }
    }
    render() {
      const { Component } = this.state;

      if (Component) {
        return <Component {...this.props} />;
      }
      return null;
    }
  };
}

But, I get an error when compiling it...

src/components/asyncComponent/index.tsx(40,27): error TS2322: Type '{ children?: ReactNode; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<P, S>> & Readonly<{ children?: ReactNode...'.
  Type '{ children?: ReactNode; }' is not assignable to type 'Readonly<P>'.
src/index.ts(3,7): error TS1141: String literal expected.
11:06:50 AM - Compilation complete. Watching for file changes.

Any ideas?

2 Answers 2

3
+50

I will try my best to explain what went wrong and how it got solved in the latest release of typescript.

Reason:

The reason for change in behavior is that in 2.3, Similar to object literal expression which contains freshness flag, JSXAttributes are type-check too(this means that excess properties are not allowed)

Solution Proposed: - Refer the Reference link

  1. Only contain explicitly attributes -> no excess properties allowed
  2. Contain spread attributes (even with explicit attributes) -> 1. check type assignability (allow access properties) 2. for each explicit attributes check if the attribute name match the target name.

This issue is being apparently solved in 2.3.3 latest stable version and 2.4.0 dev as well.

Use npm install typescript@next for the nightly build that is 2.4.0 dev or update the typescript version to latest stable(2.3.3)

Reference : Issuse Tracker

Sign up to request clarification or add additional context in comments.

Comments

2

You example compiles fine without errors in TypeScript latest:

enter image description here

More

  • Update to typescript@next

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.