How to Type Function Return Values in TypeScript

What you’ll build or solve

You’ll declare explicit return types for functions so every return path is checked.

When this approach works best

Typing return values works best when you:

  • Export functions from a shared module
  • Build APIs or libraries that others depend on
  • Write functions with multiple return branches

It also helps when refactoring complex logic where inference may not be obvious.

This is a bad idea only if you over-annotate trivial functions where inference is already clear and simple.

Prerequisites

  • TypeScript installed
  • A .ts file
  • Basic knowledge of functions and types

Step-by-step instructions

Step 1: Add a return type after the parameter list

Place the return type after the closing parenthesis using this syntax:

function functionName(params): ReturnType {
  // logic
}

Basic example

function greet(name: string): string {
  return `Hello, ${name}`;
}

If you return the wrong type, TypeScript reports an error:

function getAge(): number {
  return "30"; // Error
}

You can use any valid TypeScript type as the return type.

Object return type

function createUser(): { id: number; name: string } {
  return { id: 1, name: "Alex" };
}

Union return type

function findUser(id: number): string | null {
  if (id === 1) {
    return "Alex";
  }

  return null;
}

No return value

function logMessage(message: string): void {
  console.log(message);
}

Async return type

async function fetchData(): Promise<string> {
  return "data loaded";
}

The syntax remains the same in every case. The only change is the type you declare.

What to look for

  • Return type appears after ) and before {
  • Every return path must match the declared type
  • Use union types when multiple outcomes are valid
  • Async functions return Promise<Type>
  • TypeScript can infer return types automatically
  • Add explicit return types for exported or complex functions
  • Use interfaces for reusable object return shapes

Examples you can copy

Example 1: Boolean result

function isAdult(age: number): boolean {
  return age >= 18;
}

The function must always return a boolean.

Example 2: API-style response

interface ApiResponse {
  success: boolean;
  message: string;
}

function createResponse(message: string): ApiResponse {
  return {
    success: true,
    message
  };
}

The returned object must match the interface.

Example 3: Safe number parsing

function parseNumber(value: string): number | null {
  const parsed = Number(value);

  if (isNaN(parsed)) {
    return null;
  }

  return parsed;
}

The union type reflects both possible outcomes.

Common mistakes and how to fix them

Mistake 1: Returning inconsistent types

You might write:

function getStatus(flag: boolean): string {
  if (flag) {
    return "Active";
  }

  return 0; // Error
}

Why it breaks: 0 is not a string.

Correct approach:

function getStatus(flag: boolean): string {
  if (flag) {
    return "Active";
  }

  return "Inactive";
}

Make sure all return paths match the declared type.

Mistake 2: Forgetting to return a value

You might write:

function multiply(a: number, b: number): number {
  a * b;
}

Why it breaks: The function declares a number return type but returns nothing.

Correct approach:

function multiply(a: number, b: number): number {
  return a * b;
}

Every declared return type must be satisfied.

Troubleshooting

  • If you see “Type ‘X’ is not assignable to type ‘Y’,” review all return statements.
  • If TypeScript says a function lacks a return statement, confirm every branch returns a value.
  • If async functions show errors, verify the return type is wrapped in Promise<>.
  • If inference produces an unexpected return type, add an explicit annotation.

Quick recap

  • Add : ReturnType after the parameter list
  • All return paths must match the declared type
  • Use unions for multiple outcomes
  • Use void when nothing is returned
  • Async functions return Promise<Type>
  • Add explicit return types for shared or complex functions