TypeScript: TypeScript Function Types

Last updated: 2026-08-26

Functions are a core construct of JavaScript, and TypeScript adds a comprehensive type system to function parameters and return values—ensuring that a function’s “inputs” and “outputs” are clearly defined.

1. Function Type Annotations

(1) Parameter and Return Value Types

TYPESCRIPT
function add(a: number, b: number): number {
  return a + b;
}

let result = add(1, 2);    // result Inferred as number
// add("1", "2");          // ❌ Parameter types do not match
// add(1);                 // ❌ Insufficient number of parameters

(2) Return Type Inference

TypeScript can infer the return type based on the return statement, but it is recommended to explicitly specify it:

TYPESCRIPT
// Return Type Inference——Can be inferred, but not recommended(It's easy to make mistakes when deriving large functions)
function multiply(a: number, b: number) {
  return a * b;   // Inference Return number
}

// Explicit Annotation——Recommendations(Purpose of the Document + Compile-time errors)
function divide(a: number, b: number): number {
  if (b === 0) throw new Error("The divisor cannot be zero.");
  return a / b;
}

(3) void return type

Use void when a function has no return value:

TYPESCRIPT
function log(message: string): void {
  console.log(message);
  // None return Statement,Or return; —— All of them void
}

(4) never returns a value

Use never when a function will never return a value—it will either throw an exception or enter an infinite loop:

TYPESCRIPT
function throwError(message: string): never {
  throw new Error(message);
}

function infiniteLoop(): never {
  while (true) { }
}
Return Type Meaning
void The function completed normally, but did not return a value
never The function never ends (throws an exception or enters an infinite loop)

▶ Example: Typed utility functions

TYPESCRIPT
function clamp(value: number, min: number, max: number): number {
  return Math.min(Math.max(value, min), max);
}

function formatCurrency(amount: number, symbol: string = "¥"): string {
  return symbol + amount.toFixed(2);
}

console.log(clamp(150, 0, 100));           // 100
console.log(clamp(-5, 0, 100));            // 0
console.log(clamp(50, 0, 100));            // 50
console.log(formatCurrency(99.5));         // ¥99.50
console.log(formatCurrency(42, "$"));      // $42.00
▶ Try it Yourself

Output:

TEXT 📖 Display only
100
0
50
¥99.50
$42.00


2. Optional Parameters and Default Parameters

(1) Optional parameter ?

TYPESCRIPT
function greet(name: string, title?: string): string {
  if (title) {
    return `${title} ${name}`;
  }
  return `Hello,${name}`;
}

console.log(greet("Charlie"));           // "Hello,Charlie"
console.log(greet("Charlie", "Engineer"));  // "Engineer Charlie"
⚠️ Rule: Optional parameters must follow required parameters. function greet(title?: string, name: string) will result in an error.

(2) Default Parameters

TYPESCRIPT
function createUser(name: string, role: string = "viewer", active: boolean = true): string {
  return `${name},Characters:${role},${active ? "Active" : "Not activated"}`;
}

console.log(createUser("Charlie"));                       // Charlie,Characters:viewer,Active
console.log(createUser("Diana", "editor"));             // Diana,Characters:editor,Active
console.log(createUser("Eric", "admin", false));       // Eric,Characters:admin,Not activated

(3) Optional Parameters vs. Default Parameters

Feature Optional Parameter title?: string Default Parameter role: string = "viewer"
When called Optional; value is undefined Optional; value is the default
Type string | undefined string (not the undefined union)
Recommendation The value may indeed be undefined In most cases—it’s better to have a reasonable default value


3. Remaining Parameters

Use the ... syntax to collect the remaining parameters into an array:

TYPESCRIPT
function sum(first: number, ...rest: number[]): number {
  return rest.reduce((total, n) => total + n, first);
}

console.log(sum(1));             // 1
console.log(sum(1, 2));         // 3
console.log(sum(1, 2, 3, 4));   // 10

(1) The remaining parameters must be of array type

TYPESCRIPT
function logAll(prefix: string, ...messages: string[]): void {
  messages.forEach(msg => console.log(`${prefix}: ${msg}`));
}

logAll("DEBUG", "Start the service", "Connect to the Database", "Ready");

Output:

TEXT 📖 Display only
DEBUG: Start the service
DEBUG: Connect to the Database
DEBUG: Ready


4. Function-Type Expressions

Functions can also be passed by value—in which case, a function type expression is used to specify the type:

(1) Type aliases define function types

TYPESCRIPT
type MathOperation = (a: number, b: number) => number;

let add: MathOperation = (a, b) => a + b;
let subtract: MathOperation = (a, b) => a - b;
let multiply: MathOperation = (a, b) => a * b;

console.log(add(10, 5));       // 15
console.log(subtract(10, 5));  // 5
console.log(multiply(10, 5));  // 50

(2) Callback Function Types

The most common use of function types—describing the signature of a callback function:

TYPESCRIPT
function fetchData(url: string, onSuccess: (data: string) => void, onError: (error: Error) => void): void {
  // Simulating Asynchronous Operations
  if (url.startsWith("https://")) {
    onSuccess("Data loaded successfully");
  } else {
    onError(new Error("Supports only HTTPS"));
  }
}

fetchData(
  "https://api.example.com",
  data => console.log(data),         // ✅ (data: string) => void
  error => console.log(error.message) // ✅ (error: Error) => void
);

(3) Defining Function Types Using Interfaces

TYPESCRIPT
interface Comparator {
  (a: number, b: number): number;
}

let ascending: Comparator = (a, b) => a - b;
let descending: Comparator = (a, b) => b - a;

let nums = [3, 1, 4, 1, 5];
console.log([...nums].sort(ascending));   // [1, 1, 3, 4, 5]
console.log([...nums].sort(descending));  // [5, 4, 3, 1, 1]


5. Function Overloading

Function overloading allows a single function name to support different combinations of argument types—TypeScript’s overloading follows a “declaration + implementation” pattern:

(1) Basic Syntax

TYPESCRIPT
// Overloaded Signatures——Describe the return type for each parameter combination
function format(value: number): string;
function format(value: string): string;
function format(value: Date): string;

// Implementing Signatures——Must be compatible with all overloaded signatures
function format(value: number | string | Date): string {
  if (typeof value === "number") {
    return value.toFixed(2);
  } else if (typeof value === "string") {
    return value.trim();
  } else {
    return value.toISOString();
  }
}

console.log(format(3.14));             // "3.14"
console.log(format("  hello  "));      // "hello"
console.log(format(new Date()));       // "2024-..."

(2) Overloading Order

TypeScript matches overloaded methods in the order they are declared, from top to bottom—so more specific overloads should be placed first:

TYPESCRIPT
// ✅ Correct Order——The specifics come first
function process(value: string): string;
function process(value: any): unknown;

// ❌ Incorrect Order——any Matches all parameters,The overloaded version that comes later will never be called.
// function process(value: any): unknown;
// function process(value: string): string;

▶ Example: Overloading to Implement Type-Safe Event Handling

TYPESCRIPT
function on(event: "click", handler: (x: number, y: number) => void): void;
function on(event: "keydown", handler: (key: string) => void): void;
function on(event: string, handler: Function): void {
  console.log(`Registration Event:${event}`);
  // Implementation details omitted...
}

// Automatically determines the correct parameter types upon invocation
on("click", (x, y) => {
  console.log(`Click here:(${x}, ${y})`);   // x, y Inferred as number
});

on("keydown", (key) => {
  console.log(`Press the button:${key}`);           // key Inferred as string
});
▶ Try it Yourself

Output:

TEXT 📖 Display only
Registration Event:click
Registration Event:keydown


6. Types of Arrow Functions

(1) Type annotations for arrow functions

TYPESCRIPT
const add = (a: number, b: number): number => a + b;

// When acting as a callback,Parameter types can usually be inferred
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2);       // n Inferred as number
const asStrings = nums.map(n => String(n)); // n Inferred as number

(2) Arrow Functions and this

Arrow functions do not bind their own this—they inherit the outer this:

TYPESCRIPT
class Timer {
  seconds = 0;

  start() {
    // Arrow Functions——this Orientation Timer Examples
    setInterval(() => {
      this.seconds++;
      console.log(`${this.seconds}s`);
    }, 1000);
  }

  startBroken() {
    // Ordinary Functions——this Points to the global or undefined(Strict Mode)
    setInterval(function () {
      // this.seconds++;  // ❌ Runtime this No Timer
    }, 1000);
  }
}

▶ Example: Rest Parameters and Function Overloads

TYPESCRIPT
// Rest parameters — collecting variable arguments
function log(context: string, ...messages: string[]): void {
  console.log(`[${context}] ${messages.join(", ")}`);
}

log("App", "started", "initialized", "ready");
// [App] started, initialized, ready

// Function overloads — different return types per signature
function parse(input: string): Date;
function parse(input: number): Date;
function parse(input: string | number): Date {
  return typeof input === "string"
    ? new Date(input)
    : new Date(input);
}

let fromStr = parse("2024-01-01");
let fromNum = parse(1704067200000);
console.log(fromStr.toISOString());  // "2024-01-01T00:00:00.000Z"
▶ Try it Yourself

Output:

TEXT 📖 Display only
[App] started, initialized, ready
2024-01-01T00:00:00.000Z

❓ FAQ

Q Should function return types be explicitly specified?
A It is recommended to specify them. Although TypeScript can infer them, explicit specification offers three benefits: (1) Documentation—the return type is immediately apparent; (2) Prevention of accidentally returning the wrong type; (3) Better error localization—errors are reported in the function signature rather than at the point of call. You can omit the return type for small functions (single-line return), but it’s recommended to specify it for functions longer than three lines.
Q What is the difference between the return types void and undefined?
A void means “the function does not care about the return value”—the function may or may not have a return statement, and the caller should not use the return value. undefined is a specific type—the function explicitly returns undefined. In actual development, functions with no return value all use void.
Q What is the difference between function overloading and union type parameters?
A A union type function fn(x: string | number) can only describe that "a parameter can be one of these types," but all parameter combinations return the same type. Overloading allows for “different parameter combinations to return different types”—something union types cannot do. If the parameter types are flexible but the return type is uniform, using a union type is more concise; use overloading when different return types are required.
Q Can default parameters and optional parameters be used together?
A No. function fn(x?: string = "hi") is a syntax error—default parameters are already implied to be "optional," so there is no need to add ?. x: string = "hi" is equivalent to x?: string, but its value is "hi" rather than undefined.

📖 Summary

📝 Exercises

  1. Basic Exercise (Difficulty ⭐): Write three functions—add(a, b) for addition, subtract(a, b) for subtraction, and multiply(a, b) for multiplication—where both the parameters and return values are of type number. Use function-type expressions to uniformly declare the types.
  2. Advanced Problem (Difficulty ⭐⭐): Write a function buildQuery(params: Record<string, string | number | boolean>) that converts an object into a URL query string. For example, { page: 1, size: 10, active: true }"page=1&size=10&active=true".
  3. Challenge (Difficulty ⭐⭐⭐): Implement this using function overloading createElement(tag, props): When the tag is "input," props must be type: string; when the tag is "a," props must be href: string; and when the tag is "div," props are a generic object. Return a different type description object for each case.
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏