Functions in JavaScript and TypeScript - Simple & Code Examples

Functions in JavaScript and TypeScript - Simple & Code Examples

Functions are an essential part of any programming language and allow us to perform specific tasks and manipulate data. In both JavaScript and TypeScript, functions are a core feature, providing developers with multiple ways to define and use functions.

In this blog post, I will explore the various types of functions available in both JavaScript and TypeScript. From function declarations to arrow functions and everything in between, I will cover all the different ways to define and use functions in these programming languages.

JavaScript Functions

JavaScript provides several options for defining functions, including function declarations, named function expressions, anonymous function expressions, arrow functions, and Immediately Invoked Function Expressions (IIFEs). Let's take a look at each of these types of functions.

  • Function Declaration

A function declaration is a type of function that is declared using the function keyword followed by the function name, parameters, and the function body. It can be invoked before or after its declaration in the code.

  • Function Expression with Named Function

A function expression is a type of function that is created by assigning a function to a variable. A named function expression is a type of function expression where the function has a name.

  • Function Expression with Anonymous Function

An anonymous function expression is a type of function expression where the function does not have a name.

  • Arrow Function

An arrow function is a shorter syntax for defining anonymous function expressions. It uses the => operator to separate the function's parameters and the function body.

  • Immediately Invoked Function Expression (IIFE)

An Immediately Invoked Function Expression (IIFE) is a function that is declared and immediately invoked. It is used to create a private scope for the function.

function greetDeclaration(name) {
  console.log("Hello, " + name);
}

let greetNamed = function greetFriend(name) {
  console.log("Hello, " + name);
};

let greetAnonymous = function(name) {
  console.log("Hello, " + name);
};

let greetArrow = (name) => {
  console.log("Hello, " + name);
};

(function greetIIFE(name) {
  console.log("Hello, " + name);
})("Amy"); // outputs "Hello, Amy"

greetDeclaration("Esther"); // outputs "Hello, Esther"
greetNamed("Jane"); // outputs "Hello, Jane"
greetAnonymous("Jim"); // outputs "Hello, Jim"
greetArrow("Tom"); // outputs "Hello, Tom"

TypeScript Functions

In TypeScript, functions are similar to JavaScript functions, but they have a few additional features. One of the main features is the ability to specify the types of parameters and return values. Here's an example of a function declaration in TypeScript:

function greetDeclaration(name: string): void {
  console.log("Hello, " + name);
}
greetDeclaration("John"); // outputs "Hello, John"

In the above example, the function greetDeclaration takes a parameter name of type string and returns a value of type void.

The other types of functions in TypeScript (named function expression, anonymous function expression, arrow function, and IIFE) are similar to JavaScript functions with the addition of type annotations.

Lambda Functions

In addition to the types of functions discussed, both JavaScript and TypeScript also support the use of "lambda" functions, also known as anonymous functions. A lambda function is a function that has no name and is defined and immediately executed in a single line of code. In other words, lambda functions are unnamed function expressions.

Lambda functions are often used in functional programming to pass small, simple functions as arguments to other functions. They are also commonly used in JavaScript and TypeScript to handle events, such as button clicks or user inputs.

Here's an example of a lambda function in JavaScript:

const add = (a, b) => a + b;
console.log(add(1, 2)); // Output: 3

And here's an equivalent example in TypeScript:

const add = (a: number, b: number) => a + b;
console.log(add(1, 2)); // Output: 3

As you can see, the lambda syntax is concise and easy to understand. It allows you to define and execute a function in a single line of code, making it a popular choice for small, simple functions.

Understanding the different types of functions available in JavaScript and TypeScript is crucial for writing efficient and organized code. Whether you're a seasoned programmer or just starting out, this guide provides a comprehensive understanding of functions in these popular programming languages. With the ability to declare function parameters, return types, and use different syntax options, you have the flexibility to create functions that best fit your specific needs. Understanding the different types of functions available in JavaScript and TypeScript is an important step in mastering these programming languages and taking your coding skills to the next level.

Callback Functions

In JavaScript and TypeScript, a callback function is a function that is passed as an argument to another function and then executed within that function. This is a common pattern in asynchronous programming, where we need to wait for some action to complete before executing the callback. Here is an example of a callback function in JavaScript:

function doSomethingAsync(callback) {
  setTimeout(function() {
    callback("Done!");
  }, 1000);
}

function callback(result) {
  console.log(result);
}

doSomethingAsync(callback);

In this example, the doSomethingAsync function performs an asynchronous operation using the setTimeout method. It takes a callback function as an argument, which is executed when the operation is complete. The callback function is the callback that simply logs the result to the console.

In TypeScript, we can provide type annotations for the callback function parameter. Here is an example:

function doSomethingAsync(callback: (result: string) => void) {
  setTimeout(function() {
    callback("Done!");
  }, 1000);
}

function callback(result: string): void {
  console.log(result);
}

doSomethingAsync(callback);

In this example, we define the callback parameter to be a function that takes a string argument and returns void. This provides type safety and ensures that the callback function is called correctly.

Closures

Closures are functions that have access to variables that are outside their immediate scope. In other words, a closure is a function that has access to its own local variables, as well as the variables in the outer function's scope. This allows the inner function to access and manipulate the outer function's variables even after the outer function has returned.

Closures in JavaScript

Closures in JavaScript are often used to create private variables and functions. Private variables and functions are not accessible from outside the function, providing a degree of encapsulation and data privacy. Here's an example of a closure in JavaScript:

function outerFunction() {
  var privateVariable = "I am private";

  function innerFunction() {
    console.log(privateVariable);
  }

  return innerFunction;
}

var innerFunc = outerFunction();
innerFunc(); // Output: "I am private"

In the example above, outerFunction creates a private variable called privateVariable, and an inner function called innerFunction that has access to privateVariable. When outerFunction is called and returns innerFunction, innerFunction still has access to privateVariable, even though outerFunction has already returned. This allows us to create a private variable that cannot be accessed from outside the function.

Closures in TypeScript

Closures in TypeScript work similarly to closures in JavaScript. However, TypeScript's type system allows us to create more complex closures with stricter typing. Here's an example of a closure in TypeScript:

typescriptCopy codefunction outerFunction() {
  let privateVariable: string = "I am private";

  function innerFunction() {
    console.log(privateVariable);
  }

  return innerFunction;
}

const innerFunc = outerFunction();
innerFunc(); // Output: "I am private"

In this example, we create a private variable privateVariable and an inner function innerFunction that has access to it. The main difference between this example and the previous one is that we use TypeScript's type system to declare the variable privateVariable with the string type. This ensures that privateVariable can only hold string values, providing stronger typing and reducing the likelihood of runtime errors.

Recursive Functions

Recursive functions are functions that call themselves within their own code to solve a problem. They're useful in situations where the problem can be broken down into smaller versions of the same problem, and each sub-problem is solved in the same way. Here are some examples

Factorial function in JavaScript:

function factorial(n) {
  if (n === 1) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}

console.log(factorial(5)); // Output: 120

Factorial function in TypeScript:

function factorial(n: number): number {
  if (n === 1) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}

console.log(factorial(5)); // Output: 120

In this example, we have a recursive function that calculates the factorial of a given number. The factorial of a number is the product of all positive integers less than or equal to that number. For example, the factorial of 5 is 5 4 3 2 1 = 120.

The factorial function works by first checking if the input number is equal to 1. If it is, it returns 1, which is the base case of the function. If the input number is not 1, the function calculates the product of the input number and the result of calling the factorial function with the input number minus 1. This recursive call will continue until the input number is reduced to 1, at which point the base case will be reached, and the function will start returning values up the call stack until the final result is returned.

Fibonacci sequence in JavaScript:

function fibonacci(n) {
  if (n <= 1) {
    return n;
  } else {
    return fibonacci(n - 1) + fibonacci(n - 2);
  }
}

console.log(fibonacci(7)); // Output: 13

Fibonacci sequence in TypeScript:

function fibonacci(n: number): number {
  if (n <= 1) {
    return n;
  } else {
    return fibonacci(n - 1) + fibonacci(n - 2);
  }
}

console.log(fibonacci(7)); // Output: 13

In this example, we have a recursive function that calculates the nth number in the Fibonacci sequence. The Fibonacci sequence is a series of numbers where each number is the sum of the two preceding ones, starting from 0 and 1. For example, the first ten numbers in the Fibonacci sequence are 0, 1, 1, 2, 3, 5, 8, 13, 21, 34.

The Fibonacci function works by first checking if the input number is less than or equal to 1. If it is, it returns the input number, which is the base case of the function. If the input number is greater than 1, the function calculates the sum of the result of calling the Fibonacci function with the input number minus 1 and the result of calling the Fibonacci function with the input number minus 2. This recursive call will continue until the input number is reduced to 0 or 1, at which point the base case will be reached, and the function will start returning values up the call stack until the final result is returned.


Functions are a vital building block of programming, and both JavaScript and TypeScript provide a wide range of capabilities and features for working with them. Functions allow developers to write reusable and modular code that can be used to solve complex problems. In JavaScript, functions are first-class citizens, meaning that they can be passed around as values and used as arguments to other functions. TypeScript builds on this foundation and adds strong typing and other advanced features, making it easier to write complex and maintainable code. Regardless of the language or context, understanding how to work with functions effectively is crucial for any developer looking to write high-quality and performant code.