简体   繁体   English

基于接口的条件返回类型 typescript

[英]Conditional return type based on interface in typescript

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.我希望能够定义一个 function ,当给定一个像'chapterDates'或'kudosChecked'这样的缓存键作为字符串时,将返回缓存的值,以及该属性的正确类型。

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[] .没有解决方案似乎让 typescript 明白,当getCache('kudosChecked')的返回类型应该是number[]时。 Currently it seems to think it's number[] | { [workId: string]: string[] }目前它似乎认为它是number[] | { [workId: string]: string[] } number[] | { [workId: string]: string[] } . number[] | { [workId: string]: string[] }

Am I going about this completely wrong or something, I'm pretty new-ish to typescript?我是完全错误的还是什么,我对 typescript 很陌生?

Okay so I finally figured out how to do it by going over a lot of typescript issues.好的,所以我终于通过解决很多 typescript 问题弄清楚了如何做到这一点。 The issue that helped was microsoft/Typescript#39305 .帮助的问题是microsoft/Typescript#39305 It proposes ValueOf as它提出ValueOf

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:使用这种新类型,我们可以这样定义getCache

export async function getCache<K extends CacheId, R = ValueOf<Cache, K>>(
  id: K
): Promise<R> {
  [...]
}

Typescript playground link Typescript 操场链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM