#TypeScript Errors - Local Storage Implementation

16 messages · Page 1 of 1 (latest)

storm panther
#

Any TypeScript guru that could help me troubleshoot these errors? 😅

/createLocalStorage.ts(41,48): error TS2345: Argument of type 'string | number | symbol' is not assignable to parameter of type 'string
const storage = new MMKV();
const storageExtractors = {
  string: (key: string) => storage.getString(key),
  number: (key: string) => storage.getNumber(key),
  boolean: (key: string) => storage.getBoolean(key),
} as const;

type StorageExtractorKey = keyof typeof storageExtractors;

type StorageContent = Record<string, StorageExtractorKey>;

type LocalStorage<CurrentStorageContent extends StorageContent> = {
  addToStorage: <
    Key extends keyof CurrentStorageContent,
    Extractor extends typeof storageExtractors[CurrentStorageContent[Key]],
  >(
    key: Key,
    value: Exclude<ReturnType<Extractor>, undefined>,
  ) => void;
  getFromStorage: <
    Key extends keyof CurrentStorageContent,
    Extractor extends typeof storageExtractors[CurrentStorageContent[Key]],
  >(
    key: Key,
  ) => ReturnType<Extractor>;
};

export const createLocalStorage = <CurrentStorageContent extends StorageContent>(
  storageContent: CurrentStorageContent,
): LocalStorage<CurrentStorageContent> => {
  const getFromStorage = <Key extends keyof CurrentStorageContent>(
    key: Key,
  ): ReturnType<typeof storageExtractors[CurrentStorageContent[Key]]> => {
    const storageExtractor = storageContent[key];
    return storageExtractors[storageExtractor](key);
  };

  const addToStorage = <Key extends keyof CurrentStorageContent>(
    key: Key,
    value: Exclude<ReturnType<typeof storageExtractors[CurrentStorageContent[Key]]>, undefined>,
  ) => {
    return storage?.set(String(key), value);
  };

  return {
    getFromStorage,
    addToStorage,
  };
};

#
next-app:check:type: ../../packages/app/local-storage/createLocalStorage.ts(41,5): error TS2322: Type 'string | number | boolean | undefined' is not assignable to type 'ReturnType<{ readonly string: (key: string) => string | undefined; readonly number: (key: string) => number | undefined; readonly boolean: (key: string) => boolean | undefined; }[CurrentStorageContent[Key]]>'.

next-app:check:type:   Type 'undefined' is not assignable to type 'ReturnType<{ readonly string: (key: string) => string | undefined; readonly number: (key: string) => number | undefined; readonly boolean: (key: string) => boolean | undefined; }[CurrentStorageContent[Key]]>'.

next-app:check:type: ../../packages/app/local-storage/createLocalStorage.ts(41,48): error TS2345: Argument of type 'string | number | symbol' is not assignable to parameter of type 'string'.

next-app:check:type:   Type 'number' is not assignable to type 'string'.
robust basin
#

the top type for keyof is PropertyKey, aka string | number | symbol, representing any valid object key (+ number for convenience)
so that's likely coming from some keyof you're using. try keyof YourType & string to say "only string keys of YourType"

storm panther
# robust basin it's hard to say more than that without a reproduction, so if you can't figure i...
proud violetBOT
#

@storm panther Here's a shortened URL of your playground link! You can remove the full link from your message.

wezter96#0

Preview:```ts
import {MMKV} from "react-native-mmkv"

const storage = new MMKV()
const storageExtractors = {
string: (key: string) => storage.getString(key),
number: (key: string) => storage.getNumber(key),
boolean: (key: string) => storage.getBoolean(key),
} as const
...```

robust basin
#

yeah & string fixes that

storm panther
robust basin
storm panther
# robust basin preferably on the generic, as i described here

on my return I then get this (not seen in playground though):

Type 'CurrentStorageContent[Key]' cannot be used to index type '{ readonly string: (key: string) => string | undefined; readonly number: (key: string) => number | undefined; readonly boolean: (key: string) => boolean | undefined; }'.ts(2536)

Unless I misunderstood which generic you meant.
https://www.typescriptlang.org/play/?ts=5.4.5#code/JYWwDg9gTgLgBAbzgWWQaQGpwL5wGZQQhwDkUApgIYDGMAtAHaUzABu5dIIA1qyQNwAoQdQgMAzvEnRKAc3JwAvHAbkA7inQYAFAEohoiVJgz5AUQAeMKDRNRxSxILhxJUYA1kAuONu7kATx83D1ldJQA+Vzs5cgA6eRgAZWtQv0DdABpnFQBXEAAjcigfdKDo909wxSjpG3kE8hgAOXyiqDKsnIKICAAbKgZS-3KQqsjo03jEgCFegcoGTuzcSgdDSSFBGACwBRSpy2tbaDRAxxGIPDgdvavJ+vIjm1pocS3b-Zj5AGExGHIDHgygASuRRFAACYAHjGskycAOj2eJygZwCEQ+uwUABkINRKH0kbFoT9clAKEDib9-oD4OQrIDIQ5qeQ-kC6VFlAgcpRIZCACoQVk+aE5FzouAMgEMZlwS7XMkUums9kymDZFwuFGvKBSxmyhyfe51WI6uziADaSspyW+bNpQMt6IAui7NXAItpxfLAj50R6XKxCblyD5LNQ+rlIeRoWCYOSGALsdDzdAIgjcrLyHgPORIRmctUoqwIMBIUIXDGBgCAGKEEAiuDQyXSpkOBVwG0q+1qzllf0ZCal8uVuCRqhQJt6Ydlis5U00oGUDziUWtg1yzvdqm9x0wL0jQcBYtwHr9QZwAA+cCzMdzqnnLkSAEE+kT7ei175T3DLS7r1vbMH3zMdEnrIgmzFLU4A3GUt0Ce4dztKY+yBQM4DTPU20NG5sRNe0sKtZDVX3Z1AjdD0vR9I9YMCD1T3jRNkz2VMrBeOxMUEbAtgZSBYHHMRJHHChmHIPECQ-KZHFJclbVIjkgX1eCWT3RSD29FxFwddSfBItT1WyXQfAkwlWVk5Vd1Q-cuSiHkXA2eBwIbVkZLg9tfQCJC5J7az1LgAAyCpQmomDaIDIsfCYqAkxTY1rm0ojrR8qzHjQmByICN1bKcGDHIeM12NRRxtPSy0RhdMcXAoBMYoK8wit1K1EsauwXU6MceOEByhPgPlBWFe03POHCEK8xUUpQtKbM0rVwvon1gyjMNMIsSNo1jaLYtY+L6qeVq3mSyyptiMrXRdDMgPvPMCwYiZ7K1GrEz2gB+OJxCabQUkqWRljgJbQ30HIupyfLqyacgIMbIblBbEbNw7RCJuOhT1UPP06JPe6fSeurtLe8GAS+1JPE6IGXBBnqjHHBYpxhn9sZg3GGFeuIJ0oKA3z6PROq2KnhNK-4VwkYaAmUjzt0m1H+3mrGalyx6mme-G2aF1diZ+snee6wTqdfd9WS-RwZ3lh7qqVvH7Te-W+i-Hngb5uBmYV58mih1kMP6oUPZ9QnIZc+0MPZumpgwwXl1XDCbcNwJxA9LquqAA

proud violetBOT
#

@storm panther Here's a shortened URL of your playground link! You can remove the full link from your message.

wezter96#0

Preview:```ts
import {MMKV} from "react-native-mmkv"

const storage = new MMKV()
const storageExtractors = {
string: (key: string) => storage.getString(key),
number: (key: string) => storage.getNumber(key),
boolean: (key: string) => storage.getBoolean(key),
} as const
...```

robust basin
#

that generic, yeah. i thought you needed that cast? if not, i misunderstood

storm panther
#

Even with the cast I get the error 🤔

Type 'CurrentStorageContent[Key]' cannot be used to index type '{ readonly string: (key: string) => string | undefined; readonly number: (key: string) => number | undefined; readonly boolean: (key: string) => boolean | undefined; }'.ts(2536)
#

But it's not showing up in ts playground

robust basin
#

i used the cast you had:

proud violetBOT
#
that_guy977#0

Preview:```ts
...
export const createLocalStorage = <
CurrentStorageContent extends StorageContent

(
storageContent: CurrentStorageContent
) => {
const getFromStorage = <
Key extends keyof CurrentStorageContent & string
(
key: Key
): ReturnType<
typeof storageExtractors[CurrentStorageContent[Key]]
=> {
const storageExtractor = storageContent[key]
return storageExtractorsstorageExtractor as ReturnType<
typeof storageExtractors[CurrentStorageContent[Key]]

}
}```