'Typescript: How to map string type to generic with many different subtypes
I am trying to create a typed interface on top of local storage where I can set/get from local storage in a typed way using only a string key. I want to have a mapping of the string types to generics that allows me to have custom serialization/deserialization.
The issue I am running into is that Typescript doesn't seem to be able to properly infer the types when I use a mapping object to go from the string type to the object generic. If anyone has some good advice on the best way to go about this, that would be amazing! ❤️
I have an example below that might explain my situation better:
type LocalStorageKey = "bool_test" | "num_test";
type LocalStorageKeyInfo<T> = {
key: LocalStorageKey;
getDefault(): T;
serialize(val: T): string;
deserialize(lsVal: string | null, defaultVal: T): T;
};
const BooleanSerializer = (val: boolean) => String(val);
const BooleanDeserializer = (lsVal: string | null, defaultVal: boolean) => {
if (lsVal === null) {
return defaultVal;
} else {
return lsVal === "true";
}
};
const NumberSerializer = (val: number) => String(val);
const NumberDeserializer = (lsVal: string | null, defaultVal: number) => {
if (lsVal === null) {
return defaultVal;
} else {
return Number(lsVal);
}
};
export const BoolTestKeyInfo: LocalStorageKeyInfo<boolean> = {
key: "bool_test",
getDefault: () => false,
serialize: BooleanSerializer,
deserialize: BooleanDeserializer,
};
export const NumTestKeyInfo: LocalStorageKeyInfo<number> = {
key: "num_test",
getDefault: () => 0,
serialize: NumberSerializer,
deserialize: NumberDeserializer,
};
const keyInfoMapping = {
bool_test: BoolTestKeyInfo,
num_test: NumTestKeyInfo,
};
export function getKeyVal(key: LocalStorageKey) {
const keyInfo = keyInfoMapping[key];
try {
return keyInfo.deserialize(
window.localStorage.getItem(keyInfo.key),
// This line is the issue because deserialize's second arg is infered as never
keyInfo.getDefault()
);
} catch (e) {
return keyInfo.getDefault();
}
}
// I want x to be a boolean here
const x = getKeyVal("bool_test");
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
