@@ -24,14 +24,31 @@ import { getDataType, getInitialValue } from './functions';
2424 * @param storage The storage instance
2525 * @returns `useMMKVStorage` hook
2626 */
27- export const create =
28- < T > ( storage : MMKVInstance ) =>
29- ( key : string , defaultValue ?: any ) => {
27+ export const create : CreateType =
28+ ( storage : MMKVInstance ) =>
29+ < T = undefined > ( key : string , defaultValue ?: T ) => {
3030 if ( ! key || typeof key !== 'string' || ! storage )
3131 throw new Error ( 'Key and Storage are required parameters.' ) ;
32+
3233 return useMMKVStorage < T > ( key , storage , defaultValue ) ;
3334 } ;
3435
36+ /**
37+ * Types curried function to return differently based on the
38+ * absence of the `defaultValue` parameter.
39+ * @see {@link UseMMKVStorageType }
40+ */
41+ type CreateType = ( storage : MMKVInstance ) => {
42+ < T = undefined > ( key : string ) : [
43+ value : T | undefined ,
44+ setValue : ( value : ( T | undefined ) | ( ( prevValue : T | undefined ) => T | undefined ) ) => void
45+ ] ;
46+ < T > ( key : string , defaultValue : T ) : [
47+ value : T ,
48+ setValue : ( value : T | ( ( prevValue : T ) => T ) ) => void
49+ ] ;
50+ } ;
51+
3552/**
3653 *
3754 * useMMKVStorage Hook is like a persisted state that will always write every change in storage and update your app UI instantly.
@@ -57,18 +74,15 @@ export const create =
5774 *
5875 * @returns `[value,setValue]`
5976 */
60- export const useMMKVStorage = < T > (
77+ export const useMMKVStorage : UseMMKVStorageType = < T = undefined > (
6178 key : string ,
6279 storage : MMKVInstance ,
63- defaultValue ?: T | null | undefined
64- ) : [
65- value : T | null | undefined ,
66- setValue : ( value : T | ( ( prevValue : T | null | undefined ) => T ) ) => void
67- ] => {
80+ defaultValue ?: T
81+ ) => {
6882 const getValue = useCallback ( getInitialValue ( key , storage , 'value' ) , [ key , storage ] ) ;
6983 const getValueType = useCallback ( getInitialValue ( key , storage , 'type' ) , [ key , storage ] ) ;
7084
71- const [ value , setValue ] = useState < T | null | undefined > ( getValue ) ;
85+ const [ value , setValue ] = useState < typeof defaultValue > ( getValue ) ;
7286 const [ valueType , setValueType ] = useState ( getValueType ) ;
7387
7488 const prevKey = usePrevious ( key ) ;
@@ -154,8 +168,10 @@ export const useMMKVStorage = <T>(
154168 [ key , storage , valueType ]
155169 ) ;
156170
157- defaultValue = defaultValue === undefined ? null : defaultValue ;
158- return [ valueType === 'boolean' ? value : value || defaultValue , setNewValue ] ;
171+ return [
172+ valueType === 'boolean' || valueType === 'number' ? value : value || defaultValue ,
173+ setNewValue
174+ ] ;
159175} ;
160176
161177function usePrevious ( value : any ) {
@@ -167,3 +183,18 @@ function usePrevious(value: any) {
167183
168184 return ref . current ;
169185}
186+
187+ /**
188+ * Uses typescript's {@link https://www.typescriptlang.org/docs/handbook/interfaces.html#function-types anonymous function overloading}
189+ * to mimic React's `useState` typing.
190+ */
191+ type UseMMKVStorageType = {
192+ < T = undefined > ( key : string , storage : MMKVInstance ) : [
193+ value : T | undefined ,
194+ setValue : ( value : ( T | undefined ) | ( ( prevValue : T | undefined ) => T | undefined ) ) => void
195+ ] ;
196+ < T > ( key : string , storage : MMKVInstance , defaultValue : T | undefined ) : [
197+ value : T ,
198+ setValue : ( value : T | ( ( prevValue : T ) => T ) ) => void
199+ ] ;
200+ } ;
0 commit comments