Skip to content

Commit 9226a7d

Browse files
authored
Allow to bind EventCallable<void> to an optional callback (#92)
fix: allow to bind event without payload to an optional callback
1 parent 0141018 commit 9226a7d

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

public-types/reflect.d.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,21 @@ type Hooks<Props> = {
1818
| ((props: Props) => unknown);
1919
};
2020

21+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
22+
type VoidCallback<T> = T extends (...args: any[]) => infer R ? () => R : never;
23+
2124
/**
2225
* `bind` object type:
2326
* prop key -> store (unwrapped to reactive subscription) or any other value (used as is)
24-
*
25-
* Also handles some edge-cases like enforcing type inference for inlined callbacks
2627
*/
2728
type BindFromProps<Props> = {
2829
[K in keyof Props]?: K extends UnbindableProps
2930
? never
30-
: Props[K] extends (...args: any[]) => any
31-
? // To force TS infer types for any provided callback
32-
| ((...args: Parameters<Props[K]>) => ReturnType<Props[K]>)
33-
// Edge-case: allow to pass an event listener without any parameters (e.g. onClick: () => ...)
34-
| (() => ReturnType<Props[K]>)
35-
// Edge-case: allow to pass a Store, which contains a function
31+
:
3632
| Store<Props[K]>
37-
: Store<Props[K]> | Props[K];
33+
| Props[K]
34+
// case: allow Event<void> for callbacks with arbitrary arguments
35+
| VoidCallback<Props[K]>;
3836
};
3937

4038
/**

type-tests/types-reflect.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,26 @@ import { expectType } from 'tsd';
210210
expectType<React.FC>(ReflectedButton);
211211
}
212212

213+
// reflect should allow passing Event<void> as callback to optional event handlers
214+
{
215+
const Button: React.FC<{
216+
onOptional?: React.EventHandler<React.MouseEvent<HTMLButtonElement>>;
217+
onNull: React.MouseEventHandler<HTMLButtonElement> | null;
218+
}> = () => null;
219+
220+
const event = createEvent<void>();
221+
222+
const ReflectedButton = reflect({
223+
view: Button,
224+
bind: {
225+
onOptional: event,
226+
onNull: event,
227+
},
228+
});
229+
230+
expectType<React.FC>(ReflectedButton);
231+
}
232+
213233
// reflect should not allow binding ref
214234
{
215235
const Text = React.forwardRef(

0 commit comments

Comments
 (0)