better way to type props with default props

import { mergeProps, type JSX } from "solid-js";

// helper type which creates props type from defaultprops + adds children
// this would be somewhere in global.d.ts or imported.
type p<T extends Record<string, unknown>> = Partial<T> & { children?: JSX.Element; }

const defaultProps = {
message: "fallback message",
};

export default function Card(_props: p<typeof defaultProps>) {
const props = mergeProps(defaultProps, _props);
return <div>{props.children ?? props.message}</div>;
}
import { mergeProps, type JSX } from "solid-js";

// helper type which creates props type from defaultprops + adds children
// this would be somewhere in global.d.ts or imported.
type p<T extends Record<string, unknown>> = Partial<T> & { children?: JSX.Element; }

const defaultProps = {
message: "fallback message",
};

export default function Card(_props: p<typeof defaultProps>) {
const props = mergeProps(defaultProps, _props);
return <div>{props.children ?? props.message}</div>;
}
this is what i've come up with so far. is there a simpler/better way to type it? - the props should be optional, since i'm defining defaults for it - it should include optional children, since that's a special prop - i don't want a separate prop type for each component. - it should account for the fact that there can be additional props (thus the record string extension) - is this not a good idea? let me know! this works but, maybe i'm missing some obvious way to do it better. if this is really the general way it should be typed (like solid does not have some helper types for the pretty common scenario of default props), atleast i'd like to get rid of the typeof if possible, and move that to the helper type.
5 Replies
KraXen72
KraXen729mo ago
here's my playground link
KraXen72
KraXen729mo ago
Solid Playground
Quickly discover what the solid compiler will generate from your JSX template
KraXen72
KraXen729mo ago
having to type default props this awkwardly feels like several steps backward coming from svelte, but there's enough of an IKEA effect (i built it myself, so it must be good) where i could imagine using this.
REEEEE
REEEEE9mo ago
Solid provides the ParentComponent type when you want to specify that the component accepts children. I believe this only works with arrow functions
const MyComp: ParentComponent<typeof defaultProps> = (props) => {}
const MyComp: ParentComponent<typeof defaultProps> = (props) => {}
However, you can also use the ParentProps type for regular function declarations
function MyComp(props: ParentProps<typeof defaultProps>){...}
function MyComp(props: ParentProps<typeof defaultProps>){...}
KraXen72
KraXen729mo ago
okay, i'll test that and update with my experience here thanks so far okay, i'm pretty happy with
import { mergeProps, type ParentProps } from "solid-js";

// helper type which creates props type from defaultprops + adds children
// this would be somewhere in global.d.ts or imported.
type p<T extends Record<string, unknown>> = ParentProps<Partial<T>>

const defaultProps = {
message: "fallback message",
};

export default function Card(_props: p<typeof defaultProps>) {
const props = mergeProps(defaultProps, _props);
return <div>{props.children || props.message}</div>;
}
import { mergeProps, type ParentProps } from "solid-js";

// helper type which creates props type from defaultprops + adds children
// this would be somewhere in global.d.ts or imported.
type p<T extends Record<string, unknown>> = ParentProps<Partial<T>>

const defaultProps = {
message: "fallback message",
};

export default function Card(_props: p<typeof defaultProps>) {
const props = mergeProps(defaultProps, _props);
return <div>{props.children || props.message}</div>;
}
thanks! i feel like this is a pretty common pattern, and could be documented somewhere / shown in the tutorial.