Skip to content

Commit ec1371b

Browse files
author
Sebastian Silbermann
committed
Backport changes to 5.0
1 parent 310d92a commit ec1371b

5 files changed

Lines changed: 87 additions & 1 deletion

File tree

types/react/ts5.0/experimental.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ declare const UNDEFINED_VOID_ONLY: unique symbol;
4242
type VoidOrUndefinedOnly = void | { [UNDEFINED_VOID_ONLY]: never };
4343

4444
declare module '.' {
45+
// Need an interface to not cause ReactNode to be a self-referential type.
46+
interface PromiseLikeOfReactNode extends PromiseLike<ReactNode> {}
47+
interface DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES {
48+
promises: PromiseLikeOfReactNode;
49+
}
50+
4551
export interface SuspenseProps {
4652
/**
4753
* The presence of this prop indicates that the content is computationally expensive to render.

types/react/ts5.0/index.d.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,23 @@ declare namespace React {
206206
*/
207207
interface ReactNodeArray extends ReadonlyArray<ReactNode> {}
208208
type ReactFragment = Iterable<ReactNode>;
209-
type ReactNode = ReactElement | string | number | ReactFragment | ReactPortal | boolean | null | undefined;
209+
210+
/**
211+
* For internal usage only.
212+
* Different release channels declare additional types of ReactNode this particular release channel accepts.
213+
* App or library types should never augment this interface.
214+
*/
215+
interface DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES {}
216+
type ReactNode =
217+
| ReactElement
218+
| string
219+
| number
220+
| ReactFragment
221+
| ReactPortal
222+
| boolean
223+
| null
224+
| undefined
225+
| DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES[keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES];
210226

211227
//
212228
// Top Level API

types/react/ts5.0/test/experimental.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,35 @@ function Optimistic() {
150150
addToOptimisticCartTyped2(String(item));
151151
};
152152
}
153+
154+
// ReactNode tests
155+
{
156+
// @ts-expect-error
157+
const render: React.ReactNode = () => React.createElement('div');
158+
// @ts-expect-error
159+
const emptyObject: React.ReactNode = { };
160+
// @ts-expect-error
161+
const plainObject: React.ReactNode = { dave: true };
162+
const promise: React.ReactNode = Promise.resolve('React');
163+
// @ts-expect-error plain objects are not allowed
164+
<div>{{ dave: true }}</div>;
165+
<div>{Promise.resolve('React')}</div>;
166+
}
167+
168+
function elementTypeTests() {
169+
const ReturnPromise = () => Promise.resolve('React');
170+
// @ts-expect-error Needs https://github.com/DefinitelyTyped/DefinitelyTyped/pull/65135
171+
const FCPromise: React.FC = ReturnPromise;
172+
class RenderPromise extends React.Component {
173+
render() {
174+
return Promise.resolve('React');
175+
}
176+
}
177+
178+
// @ts-expect-error Needs https://github.com/DefinitelyTyped/DefinitelyTyped/pull/65135
179+
<ReturnPromise />;
180+
// @ts-expect-error Needs https://github.com/DefinitelyTyped/DefinitelyTyped/pull/65135
181+
React.createElement(ReturnPromise);
182+
<RenderPromise />;
183+
React.createElement(RenderPromise);
184+
}

types/react/ts5.0/test/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,15 @@ class RenderChildren extends React.Component<{ children?: React.ReactNode }> {
749749
// But no return results in `void`.
750750
// @ts-expect-error
751751
const noReturn: React.ReactNode = ['a', 'b'].map(label => {});
752+
753+
// @ts-expect-error
754+
const render: React.ReactNode = () => React.createElement('div');
755+
// @ts-expect-error
756+
const emptyObject: React.ReactNode = { };
757+
// @ts-expect-error
758+
const plainObject: React.ReactNode = { dave: true };
759+
// Will not type-check in a real project but accepted in DT tests since experimental.d.ts is part of compilation.
760+
const promise: React.ReactNode = Promise.resolve('React');
752761
}
753762

754763
const Memoized1 = React.memo(function Foo(props: { foo: string }) { return null; });

types/react/ts5.0/test/tsx.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,10 @@ function reactNodeTests() {
590590
}
591591
</div>;
592592
<div>{createChildren()}</div>;
593+
// @ts-expect-error plain objects are not allowed
594+
<div>{{ dave: true }}</div>;
595+
// Will not type-check in a real project but accepted in DT tests since experimental.d.ts is part of compilation.
596+
<div>{Promise.resolve('React')}</div>;
593597
}
594598

595599
function elementTypeTests() {
@@ -656,6 +660,16 @@ function elementTypeTests() {
656660
}
657661
}
658662

663+
const ReturnPromise = () => Promise.resolve('React');
664+
// @ts-expect-error experimental release channel only
665+
const FCPromise: React.FC = ReturnPromise;
666+
class RenderPromise extends React.Component {
667+
// Will not type-check in a real project but accepted in DT tests since experimental.d.ts is part of compilation.
668+
render() {
669+
return Promise.resolve('React');
670+
}
671+
}
672+
659673
// Desired behavior.
660674
// @ts-expect-error
661675
<ReturnVoid />;
@@ -727,6 +741,15 @@ function elementTypeTests() {
727741
React.createElement(ReturnReactNode);
728742
<RenderReactNode />;
729743
React.createElement(RenderReactNode);
744+
745+
// @ts-expect-error Only available in experimental release channel
746+
<ReturnPromise />;
747+
// @ts-expect-error Only available in experimental release channel
748+
React.createElement(ReturnPromise);
749+
// Will not type-check in a real project but accepted in DT tests since experimental.d.ts is part of compilation.
750+
<RenderPromise />;
751+
// Will not type-check in a real project but accepted in DT tests since experimental.d.ts is part of compilation.
752+
React.createElement(RenderPromise);
730753
}
731754

732755
function managingRefs() {

0 commit comments

Comments
 (0)