I want to create this hook in React (ts)
import { useState, useDeferredValue, useEffect } from "react";
type InitialValue<T> = T | (() => T);
function getStoredValue<T>(key: string, initialValue: InitialValue<T>) {
const savedValue = localStorage.getItem(key);
if (savedValue) return JSON.parse(savedValue) as T;
// return initialValue instanceof Function ? initialValue() : initialValue;
return typeof initialValue === "function" ? initialValue() : initialValue;
}
export default function useLocalStorage<T>(key: string, _default_value: InitialValue<T>) {
const [value, setValue] = useState(() => getStoredValue(key, _default_value));
const deferredValue = useDeferredValue(value);
useEffect(() => {
if (deferredValue) localStorage.setItem(key, JSON.stringify(deferredValue));
console.log("saved");
}, [deferredValue]);
return [value, setValue] as const;
}
how can i check for the type of initialValue
in getStoredValue
function
if i use initialValue instanceof Function
it works
but if i use typeof initialValue === "function"
i get this red-underline under initialValue()
that says:
This expression is not callable.
Not all constituents of type '(() => T) | (T & Function)' are callable.
Type 'T & Function' has no call signatures.ts(2349)
i think to use typeof is better but why i get such a message from typescript
CodePudding user response:
The usual thing is indeed typeof ___ === "function"
. I think the problem is that T
is completely unconstrained, which means that InitialValue
can be instantiated with T
being a function (which is why we see (() => T) | (T & Function)
in the error message).
If you update InitialValue
to expect that T
will not be a function, your typeof initialValue === "function"
check works as you expect:
type InitialValue<T> = T extends Function ? never : T | (() => T);