簡體   English   中英

通過 typescript 中函數的可選參數返回不同的泛型類型

[英]return different generic type via function's optional argument in typescript

背景

我想實現我自己的 usePromise,例如

  // if with filterKey(e.g `K=list`), fileNodes's type should be `FileNode`  (i.e. T[K])
  const [fileNodes, isOk] = usePromise(
    () => {
      return Promise.resolve({list:[]}) as Promise<{ list: FileNode[] }>;
    },
    { initValue: [] },
    "list",
  );

  // if with no filterKey, data's type should be `{list: FileNode[]}`  (i.e. T)
  const [data, isOk] = usePromise(
    () => {
      return Promise.resolve({list:[]}) as Promise<{ list: FileNode[] }>;
    },
    { initValue: {list:[]} }
  );

我的問題

我使用K extends keyof T檢查filterKey及其類型K

  1. 如果 K 是 T 的屬性,它應該返回T[K]
  2. 如果 K 不是 T 的屬性,它應該返回T

這是實現usePromise的代碼。 我發現K extends keyof T總是導致 false

如何修復我的代碼?

export function usePromise<T, K>(
  factory: () => Promise<T>,
  options: Options<K extends keyof T ? T[K] : T> = {},
  filterKey?: K,
): [K extends keyof T ? T[K] : T, boolean] {
  type R = K extends keyof T ? T[K] : T;
  const [state, setState] = useState<R>(
    options.initValue!,
  );
  const isLoadingRef = useRef(false);
  useEffect(() => {
    factory().then((r) => {
      if (filterKey) {
        setState((r as any)[filterKey] as unknown as R);
      } else {
        setState(r as unknown as R);
      }
    }).catch((res) => {
      if (options.onError) options.onError(res);
      else throw res;
    });
  }, []);
  return [state, isLoadingRef.current] as [R, boolean];
}

您當前的usePromise實現將K推斷為string | undefined 當您期待'list'string | undefined 您可以通過限制K的類型來解決此問題:

export function usePromise<T, K extends keyof T | undefined>

這是操場上的最小復制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM