Introduction to TypeScript Functions: Anonymous Functions and More
Tags: webdev, programming, typescript, javascript
Published: 2021-01-23 20:00:57

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

Functions are small blocks of code that take in some inputs and may return some output or have side effects. A side effect means that it modifies some variables outside the function.

We need functions to organize code into small blocks that are reusable.

Without functions, if we want to re-run a piece of code, we have to copy it in different places. Functions are critical to any TypeScript program.

In this article, we continue to look at different parts of TypeScript functions, including passing in a variable amount of arguments, recursion, function nesting, and defining functions in objects.

Calling Functions with More Arguments that Parameters
=====================================================

In TypeScript, we can call a function with more arguments than parameters. If we just pass them in without accessing them from the `argument` object, they’ll be ignored. You can get the extra arguments that aren’t in the parameters with the `argument` object and use them. The argument object has the parameters with numerical keys just like the indexes of an array. Another way to access extra arguments is through the rest parameter.

For example, if we call the `add` function with extra parameters:

```typescript
function add(a: number, b: number, ...rest: any){  
  console.log(arguments);  
  return a + b;  
}  
add(1, 2, 3);
```

The `...rest` part of the signature captures the parameters that we don’t expect to be passed in. We used the rest operator, which is indicated by the 3 periods before the word `rest` to indicate that there might be more parameters at the end after `b`. We need this in TypeScript so that we don’t get the mismatch between the number of parameters and the number of arguments passed in. In vanilla JavaScript, `...rest` is optional.

In the `console.log` call, we should get:

```
0: 1  
1: 2  
2: 3
```

Variable Scope in Functions
===========================

Functions inside shouldn’t be accessible outside of functions unless they are global variables. We should avoid defining global variables as much as we can to prevent bugs and hard to trace errors since they can be accessed anywhere in the program. To prevent defining global variables, we should use `let` to define variables and `const` to define constants. For example, we should define functions like so:

```typescript
function add(a: number, b: number){  
  let sum = a + b;  
  return sum;  
}
```

In this case, we have `sum` which is only accessible within the function since it’s defined with the `let` keyword.

Anonymous Functions
===================

Anonymous are functions with no names. Since they have no name, they cannot be referenced anywhere. They are often passed into other functions as callback functions, which is called when the function is passed into an argument. However, you can assign anonymous functions into a variable so it becomes a named function.

They can also be self executing. This is means that you can define the function and make it run immediately. For example, if we write:

```typescript
const sum = (function(a: number, b: number){  
  return a + b;  
})(1, 2);
console.log(sum) // log 3
```

We log 3 because we defined a function to add 2 numbers, and then passed in 1 and 2 as the arguments immediately after by wrapping the function in parenthesis and then passed the arguments to it.

Recursion
=========

You can call the same function from within itself in TypeScript. This is called recursion. All recursive functions must have an end condition, which is called the base case, so that it knows when it stops executing. Otherwise, you can get a function that’s called an infinite number of times, which will crash the browser.

To write a recursive function, we can write:

```typescript
function sumOfSquares(num: number): number {  
  let sum: number = Math.pow(num, 2);  
  if (num == 1) {  
    return 1  
  } else {  
    return sum + sumOfSquares(num - 1)  
  }    
}
```

In this example, we wrote a function to compute the sum of squares for a given number. We compute the square of `num` and then if we have `num` equal to 1 then we return 1. Otherwise, we return the sum of `sum` plus the result of call `sumOfSquares` on `num — 1` . We keep reducing `num` so that we can reach our base case of 1, adding up the results while doing so.

Nesting Functions
=================

Functions can be nested within each other. This means that we can define a function inside another function. For example, we can write:

```typescript
function convertToChicken(name: string){  
  function getChickenName(name: string){  
    return `Chicken ${name}`;  
  }  
  return getChickenName(name)  
}
```

In this case, we called `getChickeName` inside the `convertToChicken` call. So if we write `convertToChicken('chicken')` , then we get `'Chicken chicken'` since we called get `getChickeName` and returned the result. The scope of variables is the name. `let` and `const` are block-scoped so they cannot be accessed outside of the original function that’s defined, but they are available in the nested function, so if we have:

```typescript
function convertToChicken(name: string) {  
  let originalName = name;  function getChickenName(newName: string) {  
    console.log(originalName)  
    return `Chicken ${newName}`;  
  }  
  return getChickenName(name)  
}
```

Then `originalName` will still be defined in the `console.log`.

Defining Function in an Object
==============================

We can define a function in an object in a few ways. We can use the `function` keyword or arrow function as usual, but we can also write it with a shorthand for the `function` keyword. For example, if we have a `bird` object and we want to define the `chirp` function, we can write:

```typescript
const bird = {  
 chirp: function(){  
   console.log('chirp', this)  
  }  
}
```

or use the following shorthand:

```typescript
const bird = {  
 chirp(){  
   console.log('chirp', this)  
  }  
}
```

The 2 are the same since the `chirp` function will have the `bird` object as the value of `this`.

On the other hand, if you use an arrow function:

```typescript
const bird = {  
 chirp: () => {  
   console.log('chirp', this)  
  }  
}
```

We’ll get an error from the Typescript compiler because the value of `this` is the `globalThis` value, which the TypeScript compiler doesn’t allow. We get the error “The containing arrow function captures the global value of ‘this’.(7041)” when we try to compile the code above.

TypeScript functions allow us to organize code into small parts that can be reused. There’re many ways to define a function, but sticking to the commonly recommended ways like using arrow functions and not using `arguments` too much is recommended.