First, please don't try to persuade to use the React Hooks API. I need and want the class API, and that's it.
In below React class component, the PartialsFlags
is the associative array-like object which depends on specific inheritor.
import React from "react";
abstract class Gallery<PartialsFlags extends Readonly<{ [key: string]: boolean | undefined; }>>
extends React.Component<Gallery.Properties<PartialsFlags>>
{
protected get mustRenderAllPartials(): boolean {
return Object.values(this.props.partialsFlags).every((value: boolean | undefined): boolean => value === true);
}
}
namespace Gallery {
export type Properties<PartialsFlags extends Readonly<{ [key: string]: boolean | undefined; }>> = Readonly<{
mustVisuallyHideTopHeading: boolean;
mustVisuallyHideAllHeadings: boolean;
partialsFlags: PartialsFlags;
}>;
}
Below component extends the Gallery
:
class AdmonitionBlockGallery extends Gallery<AdmonitionBlockGallery.PartialsFlags> {
public render(): React.ReactNode {
return <></>;
}
}
namespace AdmonitionBlockGallery {
export type PartialsFlags = Readonly<{
minimal: boolean;
titles: boolean;
// ...etc.
}>;
}
Now if I'll try to use the AdmonitionBlockGallery
component:
import AdmonitionBlockGallery from "./_AdmonitionBlockGallery";
import React from "react";
import { createRoot } from "react-dom/client";
import { getExpectedToBeSingleDOM_Element } from "@yamato-daiwa/es-extensions-browserjs";
import { isNonEmptyString } from "@yamato-daiwa/es-extensions";
const applicationRootElement: HTMLElement = getExpectedToBeSingleDOM_Element({
selector: "#APPLICATION",
expectedDOM_ElementSubtype: HTMLElement
});
const hasPartialNameBeenSpecified: boolean = isNonEmptyString(applicationRootElement.dataset.partial_name);
createRoot(applicationRootElement).render(
<AdmonitionBlockGallery
mustVisuallyHideTopHeading={ applicationRootElement.dataset.must_visually_hide_top_heading === "" }
mustVisuallyHideAllHeadings={ applicationRootElement.dataset.must_visually_hide_all_headings === "" }
partialsFlags={
{
minimal:
!hasPartialNameBeenSpecified || applicationRootElement.dataset.partial_name === "MINIMAL",
titles:
!hasPartialNameBeenSpecified || applicationRootElement.dataset.partial_name === "TITLES",
// ...
}
}
/>
);
... I'll get the pretty complicated TypeScript error:
TS2786: AdmonitionBlockGallery cannot be used as a JSX component.
Its type typeof AdmonitionBlockGallery is not a valid JSX element type.
Type 'typeof AdmonitionBlockGallery' is not assignable to type 'new (props: any, deprecatedLegacyContext?: any) => Component<any, any, any>'.
Construct signature return types AdmonitionBlockGallery and Component<any, any, any> are incompatible.
The types returned by render() are incompatible between these types.
Type React.ReactNode is not assignable to type
import("D:/***Frontend/FrameworksIntegrations/React/Package/node_modules/@types/react/index").ReactNode
Type
ReactElement<any, string | JSXElementConstructor<any>>
is not assignable to type ReactNode
Property children is missing in type
ReactElement<any, string | JSXElementConstructor<any>>
but required in type ReactPortal
From the viewpoint of JavaScript/JSX, above components are completely valid, and although I have omitted the return value in render
method of AdmonitionBlockGallery
class, I have checked that components has been rendered correctly.
The TS2786: AdmonitionBlockGallery cannot be used as a JSX component
error has disappeared once I have updated
"@types/react": "18.0.26"
"@types/react-dom": "18.0.10"
to
"@types/react": "18.3.5"
"@types/react-dom": "18.3.0"