Skip to content

Commit

Permalink
StoreName type check not depends on infer
Browse files Browse the repository at this point in the history
  • Loading branch information
AkifumiSato committed Sep 12, 2023
1 parent 1601b67 commit 691cb76
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 15 deletions.
8 changes: 6 additions & 2 deletions apps/example-next/src/components/Counter.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
"use client";

import { useLocationState, StoreName, Refine } from "@location-state/core";
import {
useLocationState,
DefaultStoreName,
Refine,
} from "@location-state/core";
import { z, ZodType } from "zod";

const zodRefine =
Expand All @@ -10,7 +14,7 @@ const zodRefine =
return result.success ? result.data : undefined;
};

export function Counter({ storeName }: { storeName: StoreName }) {
export function Counter({ storeName }: { storeName: DefaultStoreName }) {
const [counter, setCounter] = useLocationState({
name: "counter",
defaultValue: 0,
Expand Down
4 changes: 2 additions & 2 deletions apps/example-next/src/components/List.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";

import { useLocationState, StoreName } from "@location-state/core";
import { useLocationState, DefaultStoreName } from "@location-state/core";

export function List({ storeName }: { storeName: StoreName }) {
export function List({ storeName }: { storeName: DefaultStoreName }) {
const [displayList, setDisplayList] = useLocationState({
name: "display-list",
defaultValue: false,
Expand Down
24 changes: 14 additions & 10 deletions packages/location-state-core/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import { LocationStateContext } from "./context";
import { StoreName } from "./types";
import { DefaultStoreName } from "./types";
import { useCallback, useContext, useState, useSyncExternalStore } from "react";

export type Refine<T> = (value: unknown) => T | undefined;

export type LocationStateDefinition<T> = {
export type LocationStateDefinition<
T,
StoreName extends string = DefaultStoreName,
> = {
name: string;
defaultValue: T;
storeName: StoreName | string;
// Avoid inference to rigorously check type arguments
storeName: StoreName extends infer S ? S : never;
refine?: Refine<T>;
};

type Updater<T> = (prev: T) => T;
type UpdaterOrValue<T> = T | Updater<T>;
type SetState<T> = (updaterOrValue: UpdaterOrValue<T>) => void;

const useStore = (storeName: StoreName | string) => {
const useStore = (storeName: DefaultStoreName | string) => {
const { stores } = useContext(LocationStateContext);
const store = stores[storeName];
if (!store) {
Expand All @@ -25,16 +29,16 @@ const useStore = (storeName: StoreName | string) => {
return store;
};

export const useLocationState = <T>(
definition: LocationStateDefinition<T>,
export const useLocationState = <T, StoreName extends string>(
definition: LocationStateDefinition<T, StoreName>,
): [T, SetState<T>] => {
const storeState = useLocationStateValue(definition);
const setStoreState = useLocationSetState(definition);
return [storeState, setStoreState];
};

export const useLocationStateValue = <T>(
definition: LocationStateDefinition<T>,
export const useLocationStateValue = <T, StoreName extends string>(
definition: LocationStateDefinition<T, StoreName>,
): T => {
const { name, defaultValue, storeName, refine } = useState(definition)[0];
const store = useStore(storeName);
Expand All @@ -56,8 +60,8 @@ export const useLocationStateValue = <T>(
return storeState;
};

export const useLocationSetState = <T>(
definition: LocationStateDefinition<T>,
export const useLocationSetState = <T, StoreName extends string>(
definition: LocationStateDefinition<T, StoreName>,
): SetState<T> => {
const { name, defaultValue, storeName, refine } = useState(definition)[0];
const store = useStore(storeName);
Expand Down
2 changes: 1 addition & 1 deletion packages/location-state-core/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// <reference types="navigation-api-types" />

export type StoreName = "session" | "url";
export type DefaultStoreName = "session" | "url";

export type Syncer = {
key(): string | undefined;
Expand Down

0 comments on commit 691cb76

Please sign in to comment.