網站搜尋

有沒有辦法在 TypeScript 中遞歸展開一個函數類型?


假設我們有以下類型 I:

type I = () => () => () => "a" | "b" | "c";

有沒有一種方法可以創建一個通用類型 Unwrap,使得 Unwrap<I> 評估為 "a" | "b" | "c"?

type I = () => () => () => "a" | "b" | "c";

type Result = Unwrap<I>; // "a" | "b" | "c"

以下(當然)會產生循環錯誤:

type Unwrap<
  T extends (...args: any[]) => any,
  R = ReturnType<T>
> = R extends (...args: any[]) => any
  ? Unwrap<R>
  : R;

任何幫助都將不勝感激。謝謝!

答案#1

好吧,這就是在 TypeScript 3 中有效的技巧。其實並沒有那麼糟糕。

type I = () => (() => (() => "a" | "b" | "c")) | "e" | (() => "f" | "g");

type Unwrap<T> =
    T extends (...args: any[]) => infer R
        ? { 0: Unwrap<R> }[T extends any ? 0 : never] // Hack to recurse.
    : T;

type Result = Unwrap<I>;
// type Result = "e" | "a" | "b" | "c" | "f" | "g";

遊樂場連結

答案#2

如上方評論所列,Unwrap 類型在 TypeScript 4.1(即將發佈)中可用。