# How to Specify the Return Type for a TypeScript Arrow Function

> Learn to specify the return type for a TypeScript arrow function. Add a colon and type annotation after the parameter list for clearer code and better type safety. Improve your TypeScript skills.

- Repository: [Microsoft/TypeScript](https://github.com/microsoft/typescript)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Place a colon and the type annotation immediately after the parameter list and before the fat arrow, like `(param: string): number => param.length`.**

When working with the microsoft/TypeScript compiler, you can specify the return type for a TypeScript arrow function by adding an explicit type annotation between the closing parenthesis of the parameters and the `=>` token. This annotation is stored in the `type` property of the `ArrowFunction` AST node and used by the type checker to validate return statements.

## Syntax for Explicit Return Type Annotations

To specify a return type, place a colon followed by the type immediately after the closing parenthesis of the parameter list:

```typescript
const functionName = (param: Type): ReturnType => expression;

```

This syntax applies to all arrow function variations, including those with single parameters, multiple parameters, and no parameters.

Here are practical examples demonstrating different return type annotations:

```typescript
// Simple number return type
const square = (n: number): number => n * n;

// String return type with multiple parameters
const concat = (a: string, b: string): string => a + b;

// Object return type using a type alias
type Point = { x: number; y: number };
const makePoint = (x: number, y: number): Point => ({ x, y });

// Void return type for functions that don't return a value
const log = (msg: string): void => {
    console.log(msg);
};

// Generic arrow function with constrained return type
const identity = <T>(value: T): T => value;

// Async arrow function with Promise return type
const fetchJson = async (url: string): Promise<any> => {
    const response = await fetch(url);
    return response.json();
};

```

## How the TypeScript Compiler Processes Return Types

The TypeScript compiler stores explicit return type annotations in the Abstract Syntax Tree (AST) and uses them during type checking and emit phases.

### AST Representation and the ArrowFunction Interface

According to the microsoft/TypeScript source code, the `ArrowFunction` interface in [`src/lib/typescript.d.ts`](https://github.com/microsoft/TypeScript/blob/main/src/lib/typescript.d.ts) (around line 4998) declares a `type` property that holds the return type annotation:

```typescript
interface ArrowFunction extends SignatureDeclaration, JSDocContainer {
    readonly kind: SyntaxKind.ArrowFunction;
    readonly equalsGreaterThanToken: EqualsGreaterThanToken;
    readonly body: ConciseBody;
    readonly type?: TypeNode;  // The explicit return type annotation
}

```

When you specify a return type, the parser creates a `TypeNode` representing that type and assigns it to the `type` property. If you omit the annotation, this property remains `undefined`, and the type checker infers the return type from the function body.

### Factory Function and Node Creation

The compiler uses the `createArrowFunction` factory method in [`src/compiler/factory/nodeFactory.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/factory/nodeFactory.ts) (around line 3246) to construct arrow function nodes. This factory accepts an optional `type` parameter that becomes the return type annotation on the resulting AST node:

```typescript
// Simplified representation of the factory signature
function createArrowFunction(
    modifiers: readonly Modifier[] | undefined,
    typeParameters: readonly TypeParameterDeclaration[] | undefined,
    parameters: readonly ParameterDeclaration[],
    type: TypeNode | undefined,  // The explicit return type
    equalsGreaterThanToken: EqualsGreaterThanToken,
    body: ConciseBody
): ArrowFunction;

```

When the parser encounters a return type annotation in your source code, it passes the parsed `TypeNode` to this factory, ensuring the explicit type is preserved in the AST for subsequent compiler phases.

## Why Explicit Return Types Matter

Explicit return type annotations serve critical functions across type checking, editor tooling, and declaration file generation.

### Type Checking and Validation

The TypeScript type checker uses the explicit return type to validate that all return statements within the function body are assignable to the declared type. When checking an arrow function, the compiler reads the `type` property from the `ArrowFunction` node (if present) and uses it as the expected return type for the function signature.

If you annotate a return type as `number` but return a string, the checker reports an error because the actual return type is not assignable to the annotated `NumberKeyword` type node stored in the AST.

### Editor Tooling and Refactorings

Editor features such as quick info, signature help, and refactorings rely on the `type` property of `ArrowFunction` nodes. For example, the "Infer function return type" refactoring in [`src/services/refactors/inferFunctionReturnType.ts`](https://github.com/microsoft/TypeScript/blob/main/src/services/refactors/inferFunctionReturnType.ts) (around line 15) examines existing return type annotations to determine whether to suggest adding an explicit type or modifying an existing one.

When you hover over an arrow function in an IDE, the language service reads the `type` property from the AST to display the explicit return type in the tooltip, or infers it from the body if the property is undefined.

### Declaration File Generation

When TypeScript generates [`.d.ts`](https://github.com/microsoft/TypeScript/blob/main/.d.ts) declaration files, it includes explicit return type annotations in the emitted function signatures. If you omit the return type, the compiler must infer it and may emit a broader or more complex type than intended. Explicit annotations ensure that the public API surface documented in declaration files matches your intended contract precisely.

For example, an arrow function without an explicit return type might infer a complex union type that exposes internal implementation details, whereas an explicit annotation restricts the emitted declaration to the intended public type.

## Common Patterns and Examples

Beyond basic primitives, you often need to specify return types for complex scenarios including async functions, generics, and functions returning objects or void.

### Async Arrow Functions

For async arrow functions, the return type is typically `Promise<T>` where `T` represents the resolved value type:

```typescript
const fetchUser = async (id: number): Promise<{ name: string; id: number }> => {
    const response = await fetch(`/api/users/${id}`);
    return response.json();
};

// Void async function
const delay = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms));

```

### Generic Arrow Functions

When working with generics, you can constrain the return type to the type parameter:

```typescript
// Returns the same type as the input
const identity = <T>(value: T): T => value;

// Constrained generic with specific return type
const extractKey = <T extends Record<string, any>, K extends keyof T>(
    obj: T,
    key: K
): T[K] => obj[key];

```

### Object and Array Return Types

Use type aliases or interfaces to specify complex return types:

```typescript
interface User {
    id: number;
    name: string;
    email: string;
}

const createUser = (name: string, email: string): User => ({
    id: Math.random(),
    name,
    email
});

// Array return type
const range = (start: number, end: number): number[] => 
    Array.from({ length: end - start }, (_, i) => start + i);

```

## Summary

To specify the return type for a TypeScript arrow function, place a colon and the type annotation between the parameter list and the fat arrow (`=>`). The microsoft/TypeScript compiler stores this annotation in the `type` property of the `ArrowFunction` AST node defined in [`src/lib/typescript.d.ts`](https://github.com/microsoft/TypeScript/blob/main/src/lib/typescript.d.ts), using the `createArrowFunction` factory in [`src/compiler/factory/nodeFactory.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/factory/nodeFactory.ts) to construct the node.

- **Syntax**: `(parameters): ReturnType => expression` or `(parameters): ReturnType => { statements }`
- **AST Storage**: The explicit type becomes the `type` property on the `ArrowFunction` interface; if omitted, the property is `undefined` and the checker infers from the body
- **Type Safety**: The checker validates that all return statements are assignable to the annotated type
- **Tooling**: Editor features like quick info and the "Infer function return type" refactoring in [`src/services/refactors/inferFunctionReturnType.ts`](https://github.com/microsoft/TypeScript/blob/main/src/services/refactors/inferFunctionReturnType.ts) rely on this annotation
- **Declarations**: Explicit types ensure precise [`.d.ts`](https://github.com/microsoft/TypeScript/blob/main/.d.ts) emit for public APIs

## Frequently Asked Questions

### Do I need to specify return types for arrow functions?

No, TypeScript can infer return types from the function body in most cases. However, explicit annotations improve code clarity, prevent accidental type widening, and ensure stable [`.d.ts`](https://github.com/microsoft/TypeScript/blob/main/.d.ts) declaration output. They are especially valuable for public API surfaces and complex generic functions where inference might produce unexpected union types.

### What happens if I omit the return type annotation?

When you omit the return type, the `type` property on the `ArrowFunction` AST node remains `undefined`. During type checking, the compiler analyzes the function body and infers the return type by examining all return statements. This inferred type is then used for assignment checking and editor tooling, though it may be broader or more complex than an explicit annotation would specify.

### Can I specify return types for async arrow functions?

Yes, async arrow functions use the same annotation syntax, but the return type must be a `Promise<T>` where `T` represents the resolved value type. For example: `const fetchData = async (): Promise<User[]> => { ... }`. The compiler stores this `Promise` type in the `type` property of the `ArrowFunction` node and unwraps it during type checking to validate the value returned from the async function body.

### How do I specify a return type for a generic arrow function?

Generic arrow functions support return type annotations that reference the type parameters. Place the return type annotation after the parameter list but before the `=>` token, such as `const identity = <T>(value: T): T => value`. The annotation can use the generic type parameter `T` or constrained variants like `T extends SomeType`. The compiler stores this generic type reference in the `type` property of the AST node and validates it against actual return values during type checking.