typescripttypescompiler-errorsunwraptype-inference

Is there a way to recursively unwrap a function type in TypeScript?


Let's say we have the following type I:

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

Is there a way to create a generic type Unwrap such that Unwrap<I> evaluates to "a" | "b" | "c"?

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

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

The following (ofc) produces a circularity error:

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

Any help would be greatly appreciated. Thank you!


Solution

  • Well here's the hack which works in TypeScript 3. It's actually not that awful.

    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";
    

    Playground Link