Sebi
Sebi

Reputation: 588

Is there a way to use ReturnType inside a function and reffer to the function without using its name?

Shortly said, I know I can do this:

function my_function() : Error {
  return some_generic_function<ReturnType<typeof my_function>>();
}

But is there a way to use something like the this keyword to refer to the function that contains the call, but without using it's name? Like:

function my_function() : Error {
  //This does not work, ofc
  return some_generic_function<ReturnType<typeof this>>();
}

More context:

I have multiple service-like functions that all return a Promise with the same pattern of resolve/reject. Thus, I made a generic function and want to be able to use it in each of my service-like function.

function my_generic_return<T> (data?:T, error?: Error): Promise<T> {
  return new Promise((resolve, reject) => {
    if (typeof data !== 'undefined') {
      return resolve(data);
    }
    return reject();
  });
}

function service1() : Promise<type1> {
  const data : type1 | undefined ...
  // ...
  // But this line is kinda ugly
  return my_generic_return<ReturnType<typeof service1>>()
}

function service2() : Promise<type2> {
  const data : type2 | undefined ...
  // ...
  // But this line is kinda ugly
  return my_generic_return<ReturnType<typeof service2>>()
}

One way I would like to modify that return is to have something generic instead of the name of the function inside ReturnType<typeof function_name>

Solution:

@captain-yossarian's answer is great. I let TypeScript infer my types. Here's my code:

function my_generic_return<T>(data?: NonNullable<T>, error?: Error)
  : Promise<NonNullable<T>> {
  // I use NonNullable since I never return a Promise with an undefined object.
  return new Promise((resolve, reject) => {
    if (typeof data !== 'undefined') {
      return resolve(data);
    }
    if (error instanceof Error) {
      return reject(error)
    }
    return reject(new Error("Unknown error");
  });
}


function service1() {
  const data : type1 | undefined = undefined

  // We may set data here...
 
  return my_generic_return(data)
}

function service2() {
  const data : type2 | undefined = undefined
  
  // We may set data here...
  
  return my_generic_return(data)
}

const global_data: type2 = new type2();
service2.then(
      // Param correctly seen as 'type2'
      // This is why I used NonNullable in the generic
      // Otherwise it would be seens as 'type2 | undefined'
      // because that's the type of data inside service2
      (data) => {
        global_data = data
      }
    );

Upvotes: 2

Views: 53

Answers (1)

Technically it is possible. some_generic_function should expect generic parameter.

const foo = <T,>() => null as any

function my_function(): Error {
  return foo<ReturnType<typeof my_function>>();
}

But I'm not sure if it is a good way to go.

You are passing explicit generic parameter to foo inside my_function but you don't use it at all. It will be better if you share a bit more context.

UPDATE

Rule of thumb: in 80% you should not use explicit generics when you calling a function. TS should be able to infer it.

Consider next example:

function my_generic_return<T>(data?: T, error?: Error): Promise<T> {
  return new Promise((resolve, reject) => {
    if (typeof data !== 'undefined') {
      return resolve(data);
    }
    return reject();
  });
}

type Foo = {
  tag: 'foo'
}
function service1<T>(data: T) {

  return my_generic_return(data)
}

// return type is Promise<Foo>
function service2() {
  const data: Foo = null as any

  return my_generic_return(data)
}

Upvotes: 1

Related Questions