【问题标题】:Conditional return type based on interface in typescripttypescript中基于接口的条件返回类型
【发布时间】:2020-06-30 21:19:16
【问题描述】:

我有一个这样定义的缓存(sn-p):

interface Cache {
  chapterDates: { [workId: string]: string[] };
  kudosChecked: number[];
}

export const DEFAULT_CACHE: Cache = {
  chapterDates: {},
  kudosChecked: [],
};

我希望能够定义一个函数,当给定一个像“chapterDates”或“kudosChecked”这样的缓存键作为字符串时,它将返回缓存的值,以及该属性的正确类型。

到目前为止,我已经尝试了以下使用条件类型:

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> {
  [...]
}

我也试过这个:

export async function getCache<
  T extends keyof Cache,
  R extends Cache[T]
>(id: T): Promise<R> {
  [...]
}

没有解决方案似乎让 typescript 明白,当返回类型为 e.g. getCache('kudosChecked') 应该是 number[]。目前似乎认为是number[] | { [workId: string]: string[] }

我是完全错误的还是什么,我对打字稿很陌生?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    好的,所以我终于通过解决很多打字稿问题弄清楚了如何做到这一点。有帮助的问题是microsoft/Typescript#39305。它建议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;
    

    使用这种新类型,我们可以这样定义getCache

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

    Typescript playground link

    【讨论】:

      猜你喜欢
      • 2020-10-27
      • 2020-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-03
      • 1970-01-01
      • 2023-03-30
      相关资源
      最近更新 更多