TypeScript: await Promise.all fails to resolve due to optional chaining in JSX
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
- Comment out the brokenString variable in /src/component/MyList.tsx
- Uncomment the FixPromiseError() function in src/pages/DummyPage.tsx
- 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)
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 1
- Comments: 16 (6 by maintainers)
It was so bizarre that I couldn’t resist debugging this 😅
@RyanCavanaugh Thank you so much! I think I was able to remove the React dependency. It is pushed to the “minimal” branch of my GitHub repo.
Branch: https://github.com/Fish1/bughunter/tree/minimal
/main.tsx
/MyList.tsx
OK, so it’s just these two files
listed in that order in tsconfig, with these dependencies:
I’m incredibly curious what’s going on, but would really want the react dependency stubbed out into something that still repros this before investigating further. This bug, whatever it is, is very hard to hit.
Minimal repro I have so far:
Trying to simplify further but this is very, very delicate