diff --git a/src/type.ts b/src/type.ts new file mode 100644 index 00000000..0bd44237 --- /dev/null +++ b/src/type.ts @@ -0,0 +1,2 @@ +export type RestrictArray = T extends any[] ? T : [] +export type VoidAsNull = T extends void ? null : T diff --git a/src/use-event-callback.ts b/src/use-event-callback.ts index e1b2c1e9..56c71a52 100644 --- a/src/use-event-callback.ts +++ b/src/use-event-callback.ts @@ -1,41 +1,48 @@ -import { useEffect, useMemo, useState, SyntheticEvent } from 'react' +import { useEffect, useMemo, useState } from 'react' import { Observable, BehaviorSubject, Subject, noop } from 'rxjs' -export type VoidAsNull = T extends void ? null : T +import { RestrictArray, VoidAsNull } from './type' -export type EventCallbackState<_T, E, U, I = void> = [ - (e: E) => void, - [U extends void ? null : U, BehaviorSubject, BehaviorSubject] +export type EventCallbackState = [ + (val: EventValue) => void, + [State extends void ? null : State, BehaviorSubject, BehaviorSubject | null>] +] +export type ReturnedState = [ + EventCallbackState[0], + EventCallbackState[1][0] ] -export type ReturnedState = [EventCallbackState[0], EventCallbackState[1][0]] -export type EventCallback<_T, E, U, I> = I extends void - ? (eventSource$: Observable, state$: Observable) => Observable - : (eventSource$: Observable, inputs$: Observable, state$: Observable) => Observable +export type EventCallback = Inputs extends void + ? (eventSource$: Observable, state$: Observable) => Observable + : ( + eventSource$: Observable, + inputs$: Observable>, + state$: Observable, + ) => Observable -export function useEventCallback, U = void>( - callback: EventCallback, -): ReturnedState -export function useEventCallback, U = void>( - callback: EventCallback, - initialState: U, -): ReturnedState -export function useEventCallback, U = void, I = void>( - callback: EventCallback, - initialState: U, - inputs: I, -): ReturnedState +export function useEventCallback( + callback: EventCallback, +): ReturnedState +export function useEventCallback( + callback: EventCallback, + initialState: State, +): ReturnedState +export function useEventCallback( + callback: EventCallback, + initialState: State, + inputs: RestrictArray, +): ReturnedState -export function useEventCallback, U = void, I = void>( - callback: EventCallback, - initialState?: U, - inputs?: I, -): ReturnedState { - const initialValue = (typeof initialState !== 'undefined' ? initialState : null) as VoidAsNull - const inputSubject$ = new BehaviorSubject(typeof inputs === 'undefined' ? null : inputs) - const stateSubject$ = new BehaviorSubject(initialValue) +export function useEventCallback( + callback: EventCallback, + initialState?: State, + inputs?: RestrictArray, +): ReturnedState { + const initialValue = (typeof initialState !== 'undefined' ? initialState : null) as VoidAsNull + const inputSubject$ = new BehaviorSubject | null>(typeof inputs === 'undefined' ? null : inputs) + const stateSubject$ = new BehaviorSubject(initialValue) const [state, setState] = useState(initialValue) - const [returnedCallback, setEventCallback] = useState<(e: E) => void>(noop) + const [returnedCallback, setEventCallback] = useState<(val: EventValue) => void>(() => noop) const [state$] = useState(stateSubject$) const [inputs$] = useState(inputSubject$) @@ -45,22 +52,22 @@ export function useEventCallback, U = void, I = v useEffect( () => { - const event$ = new Subject() - function eventCallback(e: E) { + const event$ = new Subject() + function eventCallback(e: EventValue) { return event$.next(e) } setState(initialValue) setEventCallback(() => eventCallback) - let value$: Observable + let value$: Observable if (!inputs) { - value$ = (callback as EventCallback)(event$, state$ as Observable) + value$ = (callback as EventCallback)(event$, state$ as Observable) } else { - value$ = (callback as any)(event$, inputs$ as Observable, state$ as Observable) + value$ = (callback as any)(event$, inputs$ as Observable, state$ as Observable) } const subscription = value$.subscribe((value) => { state$.next(value) - setState(value as VoidAsNull) + setState(value as VoidAsNull) }) return () => { subscription.unsubscribe() diff --git a/src/use-observable.ts b/src/use-observable.ts index 19d43c5f..12facd45 100644 --- a/src/use-observable.ts +++ b/src/use-observable.ts @@ -1,12 +1,12 @@ import { Observable, BehaviorSubject } from 'rxjs' import { useState, useEffect, useMemo } from 'react' +import { RestrictArray } from './type' + export type InputFactory = Inputs extends undefined ? (state$: Observable) => Observable : (inputs$: Observable>, state$: Observable) => Observable -export type RestrictArray = T extends any[] ? T : [] - export function useObservable(inputFactory: InputFactory): State | null export function useObservable(inputFactory: InputFactory, initialState: State): State export function useObservable(