Skip to content

Commit a49bc37

Browse files
committed
feat: generalize function component types
1 parent 65e9416 commit a49bc37

File tree

3 files changed

+14
-34
lines changed

3 files changed

+14
-34
lines changed

src/createElement.ts

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {bindChildren, bindProps} from "./utils"
1313
// TODO: make children optional
1414
export type FunctionComponent<
1515
Props extends {} | null | undefined,
16-
Children extends ChildrenType = ChildrenType,
16+
Children extends unknown[] = ChildrenType,
1717
Returns extends Node | JSX.Element = JSX.Element,
1818
> = (props: Props, ...children: Children) => Returns
1919

@@ -130,32 +130,15 @@ export function createElement(
130130
* @throws {Error} - If `tagNameOrFunction` is not a string or function, an errow is thrown
131131
*/
132132
export function createElement<
133-
Props extends {} | null | undefined,
134-
Children extends ChildrenType,
135-
Returns extends Node | JSX.Element,
136-
>(
137-
func: FunctionComponent<Props, Children, Returns>,
138-
props?: Props | null,
139-
...children: Children
140-
): Returns
141-
142-
/**
143-
* Creates a function component
144-
*
145-
* @param func - Function component
146-
* @param props - Props of function component
147-
* @param children - Children of this element. Can be nothing, number, string, boolean, bigint, or
148-
* more elements. An array will create multiple, flattened children.
149-
* @returns Element
150-
* @throws {Error} - If `tagNameOrFunction` is not a string or function, an errow is thrown
151-
*/
152-
export function createElement<
153-
Props extends {} | null | undefined,
133+
Props extends {} | null,
134+
Children extends unknown[],
154135
Returns extends Node | JSX.Element,
155136
>(
156-
func: FunctionComponent<Props, ChildrenType, Returns>,
157-
props?: Props | null,
158-
...children: ChildrenType
137+
...[func, props, ...children]: [
138+
func: FunctionComponent<Props, Children, Returns>,
139+
...(Props extends null ? [props?: Props | undefined] : [props: Props]),
140+
...children: Children,
141+
]
159142
): Returns
160143

161144
/**
@@ -170,12 +153,9 @@ export function createElement<
170153
* @returns Element
171154
* @throws {Error} - If `tagNameOrFunction` is not a string or function, an errow is thrown
172155
*/
173-
export function createElement<
174-
T extends string | {[key: string]: unknown} | null | undefined,
175-
Returns = void,
176-
>(
156+
export function createElement<T extends string | {[key: string]: unknown} | null, Returns = void>(
177157
tagNameOrFunction: T | ((_props: T, ..._children: ChildrenType) => Returns),
178-
props?: HTMLElementProps[T extends string ? T : ""] | null | T,
158+
props?: HTMLElementProps[T extends string ? T : ""] | null | T | undefined,
179159
...children: ChildrenType
180160
): Element | Returns {
181161
if (typeof tagNameOrFunction === "string") {
@@ -198,7 +178,7 @@ export function createElement<
198178
} else if (typeof tagNameOrFunction === "function") {
199179
// If `tagNameOrFunction` is a function, then the previous overload should've enforced that
200180
// the props are set by the function (`T`)
201-
return tagNameOrFunction(props as T, children)
181+
return tagNameOrFunction((props ?? null) as T, children)
202182
}
203183

204184
throw new Error(`Invalid element type ${typeof tagNameOrFunction}: ${tagNameOrFunction}`)

src/fragment.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ interface FragmentProps {
77
}
88

99
/* eslint-disable @typescript-eslint/naming-convention */
10-
export const Fragment: FC<FragmentProps | null | undefined, ChildrenType, DocumentFragment> = (
11-
props?,
10+
export const Fragment: FC<FragmentProps | null, ChildrenType, DocumentFragment> = (
11+
props,
1212
...children
1313
) => {
1414
const documentFragment = document.createDocumentFragment()

src/types/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {Ref} from "../createRef"
99
export type ChildType = Node | boolean | number | BigInt | string | null | undefined
1010

1111
/** All types the children parameter can be */
12-
export type ChildrenType = ChildrenType[] | ChildType[]
12+
export type ChildrenType = (ChildrenType | ChildType)[]
1313

1414
export interface EventMap extends HTMLElementEventMap, HTMLMediaElementEventMap {
1515
/* eslint-disable-next-line @typescript-eslint/naming-convention */

0 commit comments

Comments
 (0)