Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async JSX function returns #21885

Closed
dyst5422 opened this issue Feb 12, 2018 · 2 comments
Closed

Async JSX function returns #21885

dyst5422 opened this issue Feb 12, 2018 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@dyst5422
Copy link

Search Terms:
JSX async promise class functional
Code

import * as JSXML from './lib/JSXML';

const AsyncComponent = async (props: { something: number }) => {
  return new Promise(resolve => {
    setTimeout(
      () =>
        resolve(
          <div>
            {props.something}
          </div>,
        ),
      10,
    );
  });
};


async function main(): Promise<void> {

  const tree = await (<div>
      <AsyncComponent something={5}/>
    </div>);

  console.log(tree);
}

main();

JSXML.ts

declare global {
  namespace JSX {
    // tslint:disable:no-empty-interface
    interface Element extends JSXElement {}
    interface ElementAttributesProperty {
      props: {};
    }
    interface ElementChildrenAttribute {
      children: {};
    }
    interface IntrinsicElements {
      div: any;
    }
  }
}

export type JSXFactory = {
  (props: object, context?: any): JSXElement | undefined | Promise<JSXElement | undefined>;
  context?: any;
};

export interface JSXElement<Props = any, Type = string | JSXFactory> {
  type: Type;
  props: Props;
  children: JSXElement[];
}

export function createElement<Props>(
  type: string | JSXFactory,
  props: Props & {},
  ...children: JSXElement[],
): JSXElement<Props> {
  const childrenToPass = flatten<JSXElement>(children).filter(Boolean);

  return {
    type,
    props,
    children: childrenToPass,
  };
}

function flatten<T>(item: any): T[] {
  return Array.isArray(item) ? [].concat.apply([], item.map(flatten)) : item;
}

Expected behavior:

This should compile without errors to

import * as JSXML from './lib/JSXML';

const AsyncComponent = async (props: { something: number }) => {
  return new Promise(resolve => {
    setTimeout(
      () =>
        resolve(
          JSXML.createElement('div',null, props.something)
        ),
      10,
    );
  });
};


async function main(): Promise<void> {

  const tree = await (JSXML.createElement('div', null,
                         JSXML.createElement(AsyncComponent, { something: 5 })
                       ));

  console.log(tree);
}

main();

Actual behavior:

The JSX call to AsyncComponent gives the error JSX element class does not support attributes because it does not have a 'props' property.

It seems that TS believes the AsyncComponent to be a class instead of an async function.

@mhegazy
Copy link
Contributor

mhegazy commented Feb 12, 2018

This should be covered by #21699. Today we have some logic in the compiler that is tightly coupled to JSX.Element type. With #21699, we plan on making the rerun type of an SFC be anything as declare in the factory function. this should allow an SFC to be a string (react 16), or an array, a promise, or really any type.

@mhegazy mhegazy added the Duplicate An existing issue was already created label Feb 12, 2018
@dyst5422
Copy link
Author

My search skills need work.

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants