I have a cache defined like this (snippet):
interface Cache {
chapterDates: { [workId: string]: string[] };
kudosChecked: number[];
}
export const DEFAULT_CACHE: Cache = {
chapterDates: {},
kudosChecked: [],
};
I would like to be able to define a function that when given a cache key like 'chapterDates' or 'kudosChecked' as a string, would return the value of the cache, with the proper type of that property.
So far I've tried the following using conditional types:
type Test<T> = T extends 'chapterDates'
? { [workId: string]: string[] }
: T extends 'kudosChecked'
? number[]
: never;
export async function getCache<T extends keyof Cache, R extends Test<T>>(
id: T
): Promise<R> {
[...]
}
I've also tried this:
export async function getCache<
T extends keyof Cache,
R extends Cache[T]
>(id: T): Promise<R> {
[...]
}
None the solutions seem to make typescript understand that when the return type of eg getCache('kudosChecked')
should be number[]
. Currently it seems to think it's number[] | { [workId: string]: string[] }
number[] | { [workId: string]: string[] }
.
Am I going about this completely wrong or something, I'm pretty new-ish to typescript?
Okay so I finally figured out how to do it by going over a lot of typescript issues. The issue that helped was microsoft/Typescript#39305 . It proposes ValueOf
as
type KeyOf<
U,
C = unknown,
K extends U extends unknown ? keyof U : never = U extends unknown
? keyof U
: never
> = C extends unknown
? U extends unknown
? K extends unknown
? U[K] extends C
? K
: never
: never
: never
: never;
type ValueOf<U, K extends KeyOf<U> = KeyOf<U>> = U extends unknown
? K extends keyof U
? U[K]
: never
: never;
Using this new type we can then define getCache
as so:
export async function getCache<K extends CacheId, R = ValueOf<Cache, K>>(
id: K
): Promise<R> {
[...]
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.