Skip to content

Commit

Permalink
improve types for bare createElement and h calls (#3690)
Browse files Browse the repository at this point in the history
* improve types for bare createElement and h calls

* component test

* fix onInput events

* accept refless classattributes

* correct generics
  • Loading branch information
JoviDeCroock committed Aug 24, 2022
1 parent 14977dd commit 1633907
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 7 deletions.
60 changes: 54 additions & 6 deletions src/index.d.ts
Expand Up @@ -188,11 +188,35 @@ export abstract class Component<P, S> {
// -----------------------------------

export function createElement(
type: 'input',
props:
| (JSXInternal.DOMAttributes<HTMLInputElement> &
ClassAttributes<HTMLInputElement>)
| null,
...children: ComponentChildren[]
): VNode<any>;
export function createElement<
P extends JSXInternal.HTMLAttributes<T>,
T extends HTMLElement
>(
type: keyof JSXInternal.IntrinsicElements,
props: (ClassAttributes<T> & P) | null,
...children: ComponentChildren[]
): VNode<any>;
export function createElement<
P extends JSXInternal.SVGAttributes<T>,
T extends HTMLElement
>(
type: keyof JSXInternal.IntrinsicElements,
props: (ClassAttributes<T> & P) | null,
...children: ComponentChildren[]
): VNode<any>;
export function createElement<T extends HTMLElement>(
type: string,
props:
| (JSXInternal.HTMLAttributes &
JSXInternal.SVGAttributes &
Record<string, any>)
| (ClassAttributes<T> &
JSXInternal.HTMLAttributes &
JSXInternal.SVGAttributes)
| null,
...children: ComponentChildren[]
): VNode<any>;
Expand All @@ -206,11 +230,35 @@ export namespace createElement {
}

export function h(
type: 'input',
props:
| (JSXInternal.DOMAttributes<HTMLInputElement> &
ClassAttributes<HTMLInputElement>)
| null,
...children: ComponentChildren[]
): VNode<any>;
export function h<
P extends JSXInternal.HTMLAttributes<T>,
T extends HTMLElement
>(
type: keyof JSXInternal.IntrinsicElements,
props: (ClassAttributes<T> & P) | null,
...children: ComponentChildren[]
): VNode<any>;
export function h<
P extends JSXInternal.SVGAttributes<T>,
T extends HTMLElement
>(
type: keyof JSXInternal.IntrinsicElements,
props: (ClassAttributes<T> & P) | null,
...children: ComponentChildren[]
): VNode<any>;
export function h<T extends HTMLElement>(
type: string,
props:
| (JSXInternal.HTMLAttributes &
JSXInternal.SVGAttributes &
Record<string, any>)
| (ClassAttributes<T> &
JSXInternal.HTMLAttributes &
JSXInternal.SVGAttributes)
| null,
...children: ComponentChildren[]
): VNode<any>;
Expand Down
20 changes: 19 additions & 1 deletion test/ts/preact.tsx
Expand Up @@ -5,7 +5,8 @@ import {
ComponentProps,
FunctionalComponent,
AnyComponent,
h
h,
createRef
} from '../../';

interface DummyProps {
Expand Down Expand Up @@ -314,3 +315,20 @@ const acceptsNumberAsLength = <div style={{ marginTop: 20 }} />;
const acceptsStringAsLength = <div style={{ marginTop: '20px' }} />;

const ReturnNull: FunctionalComponent = () => null;

// Refs should work on elements
const ref = createRef<HTMLDivElement>();
createElement('div', { ref: ref }, 'hi');
h('div', { ref: ref }, 'hi');

// Refs should work on functions
const functionRef = createRef();
const RefComponentTest = () => <p>hi</p>;
createElement(RefComponentTest, { ref: functionRef }, 'hi');
h(RefComponentTest, { ref: functionRef }, 'hi');

// Should accept onInput
const onInput = (e: h.JSX.TargetedEvent<HTMLInputElement>) => {};
<input onInput={onInput} />;
createElement('input', { onInput: onInput });
h('input', { onInput: onInput });

0 comments on commit 1633907

Please sign in to comment.