Help with creating a builder pattern for main renderer

Wasn't sure how to fully articulate this but I want to have a class that lets me "build" the nested component structure that eventually gets passed into the render function. I think I have it working with runtime behavior, but the type definitions aren't quite right and was hoping I could get some feedback on it. Implementation
export class HOCBuilder {
private component: Component<Record<string, unknown>> = () => <></>;
private props?: ComponentProps<typeof this.component>;

with<T extends Component<ParentProps>>(
Wrapper: T,
wrapperProps?: ComponentProps<T>
): this {
const PreviousComponent = this.component;
const previousProps = this.props;
this.props = wrapperProps;

this.component = () => (
<Wrapper {...wrapperProps}>
<PreviousComponent {...previousProps} />
</Wrapper>
);
return this;
}

build(): Component {
return this.component;
}
}
export class HOCBuilder {
private component: Component<Record<string, unknown>> = () => <></>;
private props?: ComponentProps<typeof this.component>;

with<T extends Component<ParentProps>>(
Wrapper: T,
wrapperProps?: ComponentProps<T>
): this {
const PreviousComponent = this.component;
const previousProps = this.props;
this.props = wrapperProps;

this.component = () => (
<Wrapper {...wrapperProps}>
<PreviousComponent {...previousProps} />
</Wrapper>
);
return this;
}

build(): Component {
return this.component;
}
}
Usage
import { HOCBuilder, KeyboardShortcutManagerProvider } from "~/utilities";
import { type JSX } from "solid-js";
import { render } from "solid-js/web";

import App from "./App";
import { Router } from "./router";

function Foo(props: { bar: string }): JSX.Element {
return <>{props.bar}</>;
}

const Main = new HOCBuilder()
.with(Router, { root: App })
// This is giving an error! :'(
.with(Foo, { bar: "asdf" })
.with(KeyboardShortcutManagerProvider)
.build();

render(() => <Main />, document.getElementById("root")!);
import { HOCBuilder, KeyboardShortcutManagerProvider } from "~/utilities";
import { type JSX } from "solid-js";
import { render } from "solid-js/web";

import App from "./App";
import { Router } from "./router";

function Foo(props: { bar: string }): JSX.Element {
return <>{props.bar}</>;
}

const Main = new HOCBuilder()
.with(Router, { root: App })
// This is giving an error! :'(
.with(Foo, { bar: "asdf" })
.with(KeyboardShortcutManagerProvider)
.build();

render(() => <Main />, document.getElementById("root")!);
Argument of type '(props: { bar: string; }) => Element' is not assignable to parameter of type 'Component<{ children?: Element; }>'.
Types of parameters 'props' and 'props' are incompatible.
Property 'bar' is missing in type '{ children?: Element; }' but required in type '{ bar: string; }'.
Argument of type '(props: { bar: string; }) => Element' is not assignable to parameter of type 'Component<{ children?: Element; }>'.
Types of parameters 'props' and 'props' are incompatible.
Property 'bar' is missing in type '{ children?: Element; }' but required in type '{ bar: string; }'.
3 Replies
flippyflops
flippyflopsOP4mo ago
I may just be spent right now and need a break but I've tried a few variations with built in solidJS types and must be missing something 🤷🏼‍♂️
subframe7536
subframe75364mo ago
GitHub
core/src/app.ts at main · solid-hooks/core
useful hooks for solid.js. Contribute to solid-hooks/core development by creating an account on GitHub.
flippyflops
flippyflopsOP4mo ago
Ah, very nice thank you for sharing! this is almost exactly what I wanted TYVM!
Want results from more Discord servers?
Add your server