Skip to content

Commit

Permalink
Improve the type definition of useProperty.
Browse files Browse the repository at this point in the history
  • Loading branch information
megheaiulian committed Jul 26, 2024
1 parent be6feba commit 271620e
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 19 deletions.
31 changes: 17 additions & 14 deletions src/use-property.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
import { hook, Hook } from "./hook";
import { State } from "./state";
import type {
InitialState,
NewState,
StateUpdater,
StateTuple,
} from "./use-state";

type Host<T> = Element & { [key: string]: T };
type NewState<T> = T | ((previousState?: T) => T);
type StateUpdater<T> = (value: NewState<T>) => void;
type ChangeEvent<T> = {
value: T;
path: string;
};

export interface UseProperty {
<T>(property: string): StateTuple<T | undefined>;
<T>(property: string, value?: InitialState<T>): StateTuple<T>;
}

const UPPER = /([A-Z])/gu;

export const useProperty = hook(
class<T> extends Hook<[string, T], [T, StateUpdater<T>], Host<T>> {
class<T> extends Hook<[string, T], StateTuple<T>, Host<T>> {
property: string;
eventName: string;

constructor(
id: number,
state: State<Host<T>>,
property: string,
initialValue: NewState<T>
initialValue: InitialState<T>
) {
super(id, state);

Expand All @@ -46,15 +55,15 @@ export const useProperty = hook(
this.updateProp(initialValue);
}

update(ignored: string, ignored2: T): [T, StateUpdater<T>] {
update(ignored: string, ignored2: T): StateTuple<T> {
return [this.state.host[this.property], this.updater];
}

updater(value: NewState<T>): void {
const previousValue = this.state.host[this.property];

if (typeof value === "function") {
const updaterFn = value as (previousState?: T) => T;
const updaterFn = value as (previousState: T) => T;
value = updaterFn(previousValue);
}

Expand All @@ -80,16 +89,10 @@ export const useProperty = hook(
return ev;
}
}
) as <T>(
property: string,
initialValue?: T
) => readonly [
T extends (...args: any[]) => infer R ? R : T,
StateUpdater<T extends (...args: any[]) => infer S ? S : T>
];
) as UseProperty;

export const lift =
<T>(setter: (value: T) => void) =>
<T>(setter: StateUpdater<T>) =>
(ev: CustomEvent<ChangeEvent<T>>) => {
ev.preventDefault();
setter(ev.detail.value);
Expand Down
12 changes: 7 additions & 5 deletions src/use-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ const useState = hook(
constructor(id: number, state: State, initialValue: InitialState<T>) {
super(id, state);
this.updater = this.updater.bind(this);
const initial =
typeof initialValue === "function"
? (initialValue as () => T)()
: initialValue;
this.makeArgs(initial);

if (typeof initialValue === "function") {
const initFn = initialValue as () => T;
initialValue = initFn();
}

this.makeArgs(initialValue);
}

update(): StateTuple<T> {
Expand Down

0 comments on commit 271620e

Please sign in to comment.