Skip to content

Commit

Permalink
Revised Component types (children, readonly, ref)
Browse files Browse the repository at this point in the history
* Rename past `Component` type to `ComponentWithChildren`.
  Motivation: Most components don't actually support children.
  This causes a type error upon accidental passing of children /
  forces you to think about which components support children.
* Added second parameter to `ComponentWithChildren`
  to make it easier to give a custom type for `children`
  (but still defaults to useful `JSX.Element`).
* New `Component` type does not have automatic `children` property
  (like React's preferred `VoidFunctionalComponent`),
  offering another natural way to type `props.children`:
  `Component<{children: JSX.Element}>`.
* `props` argument in both `Component` and `ComponentWithChildren`
  automatically cast to `readonly` (shallow one level only),
  to avoid accidental assignment to `props.foo` (usually a getter)
  while still allowing passing mutables in props.
  Add `Props<T>` helper for this transformation.
* Add @lxsmnsyc's `Ref<T>` type so it's easy to type `props.ref`:
  `Component<{ref: Ref<Element>}>`.
  <solidjs#778 (comment)>
  Fixes solidjs#778.
  • Loading branch information
edemaine committed Mar 7, 2022
1 parent 1b729a1 commit ca992c6
Showing 1 changed file with 12 additions and 2 deletions.
14 changes: 12 additions & 2 deletions packages/solid/src/render/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ export function enableHydration() {
hydrationEnabled = true;
}

export type PropsWithChildren<P = {}> = P & { children?: JSX.Element };
export type Component<P = {}> = (props: PropsWithChildren<P>) => JSX.Element;
export type Props<P = {}> = Readonly<P>;
export type PropsWithChildren<P = {}, C = JSX.Element> =
Props<P> & { readonly children?: C };
export type Component<P = {}> = (props: Props<P>) => JSX.Element;
export type ComponentWithChildren<P = {}, C = JSX.Element> =
(props: PropsWithChildren<P, C>) => JSX.Element;
/**
* Takes the props of the passed component and returns its type
*
Expand All @@ -30,6 +34,12 @@ export type ComponentProps<T extends keyof JSX.IntrinsicElements | Component<any
: T extends keyof JSX.IntrinsicElements
? JSX.IntrinsicElements[T]
: {};
/** Type of `props.ref`, for use in `Props`.
*
* @example Props<{ref: Ref<Element>}>
*/
export type Ref<T> = T | ((val: T) => void);

export function createComponent<T>(Comp: (props: T) => JSX.Element, props: T): JSX.Element {
if (hydrationEnabled) {
if (sharedConfig.context) {
Expand Down

0 comments on commit ca992c6

Please sign in to comment.