【从零搭建税务自动化系统-前端篇】关于使用useStorage在Typescript中类型错误问题
我现在有个接口如下:
interface GlobalSettings {
navTheme: ThemeType
}
ThemeType 是上篇文章中定义的联合类型,类型为”dark“|”light“
现在有个defaultSettings默认值对象:
const defaultSettings: GlobalSetting = {
navTheme: "light"
}
我将这个defaultSettings的值初始化到pina中做状态管理,使用了vueUse工具箱,代码如下:
export const useSettingsStore = defineStore('setting', () => {
const navTheme = useStorage('navTheme', defaultSettings.navTheme)
const themeConfig = reactive({
// themeAlgorithm[navTheme.value] 这句一直会报错
/**
元素隐式具有 "any" 类型,因为类型为 "string" 的表达式不能用于索引类型 "{ readonly light: (token: SeedToken) => MapToken; readonly dark: DerivativeFunc<SeedToken, MapToken>; }"。
在类型 "{ readonly light: (token: SeedToken) => MapToken; readonly dark: DerivativeFunc<SeedToken, MapToken>; }" 上找不到具有类型为 "string" 的参数的索引签名。ts(7053)
*/
algorithm: themeAlgorithm[navTheme.value] || antdTheme.defaultAlgorithm
})
})
上面报错的意思是useStorage返回的类型是RemovableRef<string>。 那我就纳闷了,defaultSettings.navTheme 明明定义的时候是ThemeType类型,为什么useStoreage返回的是string呢?
然后去查看useStroage文档,如下是它的类型声明:
export interface Serializer<T> {
read: (raw: string) => T
write: (value: T) => string
}
export interface SerializerAsync<T> {
read: (raw: string) => Awaitable<T>
write: (value: T) => Awaitable<string>
}
export declare const StorageSerializers: Record<
"boolean" | "object" | "number" | "any" | "string" | "map" | "set" | "date",
Serializer<any>
>
export declare const customStorageEventName = "vueuse-storage"
export interface StorageEventLike {
storageArea: StorageLike | null
key: StorageEvent["key"]
oldValue: StorageEvent["oldValue"]
newValue: StorageEvent["newValue"]
}
export interface UseStorageOptions<T>
extends ConfigurableEventFilter,
ConfigurableWindow,
ConfigurableFlush {
/**
* Watch for deep changes
*
* @default true
*/
deep?: boolean
/**
* Listen to storage changes, useful for multiple tabs application
*
* @default true
*/
listenToStorageChanges?: boolean
/**
* Write the default value to the storage when it does not exist
*
* @default true
*/
writeDefaults?: boolean
/**
* Merge the default value with the value read from the storage.
*
* When setting it to true, it will perform a **shallow merge** for objects.
* You can pass a function to perform custom merge (e.g. deep merge), for example:
*
* @default false
*/
mergeDefaults?: boolean | ((storageValue: T, defaults: T) => T)
/**
* Custom data serialization
*/
serializer?: Serializer<T>
/**
* On error callback
*
* Default log error to `console.error`
*/
onError?: (error: unknown) => void
/**
* Use shallow ref as reference
*
* @default false
*/
shallow?: boolean
/**
* Wait for the component to be mounted before reading the storage.
*
* @default false
*/
initOnMounted?: boolean
}
export declare function useStorage(
key: MaybeRefOrGetter<string>,
defaults: MaybeRefOrGetter<string>,
storage?: StorageLike,
options?: UseStorageOptions<string>,
): RemovableRef<string>
export declare function useStorage(
key: MaybeRefOrGetter<string>,
defaults: MaybeRefOrGetter<boolean>,
storage?: StorageLike,
options?: UseStorageOptions<boolean>,
): RemovableRef<boolean>
export declare function useStorage(
key: MaybeRefOrGetter<string>,
defaults: MaybeRefOrGetter<number>,
storage?: StorageLike,
options?: UseStorageOptions<number>,
): RemovableRef<number>
export declare function useStorage<T>(
key: MaybeRefOrGetter<string>,
defaults: MaybeRefOrGetter<T>,
storage?: StorageLike,
options?: UseStorageOptions<T>,
): RemovableRef<T>
export declare function useStorage<T = unknown>(
key: MaybeRefOrGetter<string>,
defaults: MaybeRefOrGetter<null>,
storage?: StorageLike,
options?: UseStorageOptions<T>,
): RemovableRef<T>
正常来说useStorage应该能够根据默认值的类型,返回跟默认值类型一样的类型的,但是现实是没有,后来我给useStorage加了个范型才得到解决,代码如下:

看官方文档,我的理解是对原始类型,useStorage能够自动拆箱成正确的类型,对于其他对象类型或自定义类型,则需要显式的给到useStorage范型类型。
更多推荐



所有评论(0)