How to Get the Return Type of a Function in TypeScript?

In this tutorial, I will explain how to get the return type of a function in TypeScript. As a TypeScript developer working on projects for US-based clients, I’ve often encountered situations where knowing the return type of a function is crucial for writing type-safe and maintainable code. In this article, we’ll explore different techniques to extract and infer the return type of a function using TypeScript’s built-in utility types and syntax. Let me explain with examples.

Using the ReturnType Utility Type

TypeScript provides a handy utility type called ReturnType<Type> that allows us to extract the return type of a function. It takes a function type as a parameter and infers the return type. Here’s an example:

function getUserName(userId: number): string {
  // Fetch user name from the database based on userId
  // ...
  return 'John Doe';
}

type UserNameType = ReturnType<typeof getUserName>;
// UserNameType is inferred as string

// Print the return type of the getUserName function
console.log(typeof getUserName(123)); // Output: string

In the above code, we have a function getUserName that takes a userId of type number and returns a string representing the user’s name. By using ReturnType<typeof getUserName>, we extract the return type of the getUserName function, which is string. The resulting type is assigned to UserNameType.

The ReturnType<Type> utility type is particularly useful when dealing with complex function types or when the return type is not explicitly mentioned in the function declaration.

I executed the above code, and you can see the output in the screenshot below:

Get the Return Type of a Function in TypeScript

Check out How to Use Generic Arrow Functions in TypeScript?

Specify the Return Type Explicitly

Another way to obtain the return type of a function is by explicitly specifying it using the : ReturnType syntax after the function’s parameter list. This approach is straightforward and makes the return type clear. Here’s an example:

function calculateTotalPrice(price: number, taxRate: number): number {
  const totalPrice = price * (1 + taxRate);
  return totalPrice;
}

type TotalPriceType = ReturnType<typeof calculateTotalPrice>;
// TotalPriceType is explicitly specified as number

In this example, the calculateTotalPrice function takes price and taxRate as parameters, both of type number, and explicitly specifies the return type as number using the : number syntax. By using ReturnType<typeof calculateTotalPrice>, we can extract the return type, which is number.

Explicitly specifying the return type is beneficial when you want to enforce a specific type for the function’s return value and make it clear to other developers what the function is expected to return.

Read How to Pass a Function as a Parameter in TypeScript?

Inferring the Return Type

In some cases, TypeScript can automatically infer the return type of a function based on the types of the expressions used in the function body. This is known as type inference. Let’s see an example:

function getFullName(firstName: string, lastName: string) {
  return `${firstName} ${lastName}`;
}

type FullNameType = ReturnType<typeof getFullName>;
// FullNameType is inferred as string

In this example, the getFullName function takes firstName and lastName as parameters, both of type string, and returns their concatenation using a template literal. TypeScript infers the return type as string based on the expression used in the return statement.

Type inference is a powerful feature of TypeScript that reduces the need for explicit type annotations and makes the code more concise. However, it’s important to note that type inference may not always provide the most specific or desired type, especially in complex scenarios. In such cases, explicitly specifying the return type or using ReturnType<Type> is recommended.

Check out How to Use Default Function Parameters in TypeScript?

Handle Function Overloads

When a function has multiple overloads with different return types, obtaining the return type becomes a bit more involved. In such cases, you need to specify the specific overload signature to extract the corresponding return type. Here’s an example:

function processData(data: string): string;
function processData(data: number): number;
function processData(data: string | number): string | number {
  if (typeof data === 'string') {
    return data.toUpperCase();
  } else {
    return data * 2;
  }
}

type StringReturnType = ReturnType<typeof processData>;
// StringReturnType is string | number

type NumberReturnType = ReturnType<(data: number) => number>;
// NumberReturnType is number

In this example, the processData function has two overload signatures: one that takes a string and returns a string, and another that takes a number and returns a number. The actual implementation of the function handles both cases using a type guard.

To obtain the return type of a specific overload, you can use ReturnType<typeof processData> for the first overload, which results in string | number. Alternatively, you can specify the desired overload signature inline, like ReturnType<(data: number) => number>, to get the return type specifically for the number overload, which is number.

Best Practices

When working with function return types in TypeScript, consider the following best practices:

  • Explicitly specify the return type when it provides clarity and enhances code readability.
  • Use ReturnType<Type> when you need to extract the return type of a function, especially in complex scenarios or when the return type is not explicitly mentioned.
  • Leverage type inference when the return type can be accurately inferred based on the function’s implementation.
  • Be cautious when using type inference with function overloads and explicitly specify the desired overload signature if needed.

Conclusion

In this tutorial, I have explained various ways to obtain the return type of a function in TypeScript. By using the ReturnType<Type> utility type, explicitly specifying the return type, leveraging type inference, and handling function overloads, you can write type-safe and maintainable code.

I hope this tutorial helps you to know how to get the return type of a function in TypeScript.