Skip to content

await Promise.all fails to resolve due to optional chaining in JSX #52475

Closed
@Fish1

Description

@Fish1

Bug Report - await Promise.all fails to resolve due to optional chaining inside JSX

I am sorry if this doesn't end up being a TypeScript bug, I'm just not able to replicate this without React at the moment. This feels more like a TypeScript issue? So I'll let you guys decide.

🔎 Search Terms

await Promise.all toString JSX ReactNode

🕗 Version & Regression Information

  • This is a type checking error
  • Broken on 4.9.4, works with version 4.6.2
  • I am only able to replicate this with React 17.0.2, not react 18

⏯ Repo Link

Sorry, I have to use a repo for this. It's a bit of a setup to create the conditions for this.
https://github.com/Fish1/bughunter

💻 Code

/src/pages/HomePage.tsx

import { ReactNode } from "react";
import MyList from "../component/MyList";

function HomePage() {

  async function myUnusedFunction() {
      const getDataFetch1 = Promise.resolve(["hello", "world"])
      const getDataFetch2 = Promise.resolve([{ id: 1 }, { id: 2 }])

      const [data1, data2] = await Promise.all([
        getDataFetch1, getDataFetch2 
      ]);

      // *******************************
      // TypeScript thinks data2 is a Promise<{ id: number; }[]>
      const x = data2.map((data) => {
        return data.id.toString();
      });
   
      // *******************************
      // TypeScript thinks data1 is a Promise<string[]>
      const y = data1.map((data) => {
        return data.toString();
      });

      return { x, y };
  }

  const myNodeArray: ReactNode[] = [
    <div>hello</div>,
    <div>world</div>,
    "hello",
    "sup",
  ]

  return (
    <div>
      <h1>Home Page</h1>
      <MyList columnsCurrent={myNodeArray}/>
    </div>
  );
}

export default HomePage;

/src/component/MyList.tsx

import { ReactNode } from "react";

export interface ListThingProps {
  columnsCurrent: ReactNode[],
}

function MyList(props: ListThingProps) {
  const { columnsCurrent } = props;

  return (
    <div>
      {
        columnsCurrent.map((column, index) => {

          /**
           * *******************************************************************
           * This variable existing will cause Promise.all() to not resolve its promises.
           * *******************************************************************
           */
          const brokenString = column?.toString();

          return (
            <div key={index}>
              {/* remove {column} here to fix the Promise.all() error */}
              {column}
            </div>
          )
        })
      }
    </div>
  );
}

export default MyList;

output of npx tsc

src/pages/HomePage.tsx:14:23 - error TS2339: Property 'map' does not exist on type 'Promise<{ id: number; }[]>'.

14       const x = data2.map((data) => {
                         ~~~

  src/pages/HomePage.tsx:14:23
    14       const x = data2.map((data) => {
                             ~~~
    Did you forget to use 'await'?

src/pages/HomePage.tsx:14:28 - error TS7006: Parameter 'data' implicitly has an 'any' type.

14       const x = data2.map((data) => {
                              ~~~~

src/pages/HomePage.tsx:18:23 - error TS2339: Property 'map' does not exist on type 'Promise<string[]>'.

18       const y = data1.map((data) => {
                         ~~~

  src/pages/HomePage.tsx:18:23
    18       const y = data1.map((data) => {
                             ~~~
    Did you forget to use 'await'?

src/pages/HomePage.tsx:18:28 - error TS7006: Parameter 'data' implicitly has an 'any' type.

18       const y = data1.map((data) => {
                              ~~~~


Found 4 errors in the same file, starting at: src/pages/HomePage.tsx:14

🙁 Actual behavior

await Promise.all doesn't resolve the promises.

🙂 Expected behavior

I expect Promise.all() to resolve it's types correctly regardless of a variable in another file.

Strange Solutions that I have come up with

  1. Comment out the brokenString variable in /src/component/MyList.tsx
  2. Uncomment the FixPromiseError() function in src/pages/DummyPage.tsx
  3. Remove {column} from inside the div in /src/component/MyList.tsx

Here is a link to the TypeScript community discord, and the thread with a lots more testing.
https://discord.com/channels/508357248330760243/1068268321998372964

Video of error (incase text description wasn't clear)

Video.webm

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions