Typescript ReturnType of generic function

If you want to get some special generic type, You can use a fake function to wrap it.

const wrapperFoo = () => foo<number>()
type Return = ReturnType<typeof wrapperFoo>

More complex demo

function getList<T>(): {
  list: T[],
  add: (v: T) => void,
  remove: (v: T) => void,
  // ...blahblah
}
const wrapperGetList = () => getList<number>()
type List = ReturnType<typeof wrapperGetList>
// List = {list: number[], add: (v: number) => void, remove: (v: number) => void, ...blahblah}

This was previously impossible to do in a purely generic fashion, but will be in Typescript 4.7. The pattern is called an "Instantiation Expression". The relevant PR is here. Excerpt from the description:

function makeBox<T>(value: T) {
  return { value };
};

const makeStringBox = makeBox<string>;  // (value: string) => { value: string }
const stringBox = makeStringBox('abc');  // { value: string }

const ErrorMap = Map<string, Error>;  // new () => Map<string, Error>
const errorMap = new ErrorMap();  // Map<string, Error> ```

...

A particularly useful pattern is to create generic type aliases for applications of typeof that reference type parameters in type instantiation expressions:

type BoxFunc<T> = typeof makeBox<T>;  // (value: T) => { value: T }
type Box<T> = ReturnType<typeof makeBox<T>>;  // { value: T } type
StringBox = Box<string>;  // { value: string }

This is my currently working solution for extracting un-exported internal types of imported libraries (like knex):

// foo is an imported function that I have no control over
function foo<T>(e: T): InternalType<T> {
    return e;
}

class Wrapper<T> {
  // wrapped has no explicit return type so we can infer it
  wrapped(e: T) {
    return foo<T>(e)
  }
}

type FooInternalType<T> = ReturnType<Wrapper<T>['wrapped']>
type Y = FooInternalType<number>
// Y === InternalType<number>

I found a good and easy way to achieve this if you can change the function definition. In my case, I needed to use the typescript type Parameters with a generic function, precisely I was trying Parameters<typeof foo<T>> and effectively it doesn't work. So the best way to achieve this is changing the function definition by an interface function definition, this also will work with the typescript type ReturnType.

Here an example following the case described by the OP:

function foo<T>(e: T): T {
   return e;
}

type fooReturn = ReturnType<typeof foo<number>>; // Damn! it throws error

// BUT if you try defining your function as an interface like this:

interface foo<T>{
   (e: T): T
}

type fooReturn = ReturnType<foo<number>> //it's number, It works!!!
type fooParams = Parameters<foo<string>> //it also works!! it is [string]

//and you can use the interface in this way
const myfoo: foo<number> = (asd: number) => {
    return asd;
};

myfoo(7);