Introduction to TypeScript Functions 
Tags: webdev, programming, typescript, javascript
Published: 2021-01-23 20:01:14

**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 takes in some inputs and may return some output or have side effects. A side effect is when a function modifies some variable 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 look at how to define TypeScript functions, how to add types to functions, and passing in arguments in different ways.

Defining Functions
==================

To define a function in TypeScript, we can do the following:

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

The function above adds 2 numbers together and returns the sum. `a` and `b` are parameters, which lets us pass in arguments into the function to compute and combine them. `add` is the name of the function, which is optional in JavaScript. The `return` statement lets the result of the function be sent to another variable or as an argument of another function. This is not the only way to define a function. Another way is to write it as an arrow function:

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

The 2 are equivalent. However, if we have to manipulate `this` in the function, then the 2 aren’t the same since the arrow function will not change the value of `this` inside the function, like the function defined with the `function` keyword does. We can assign the function to a variable since functions are objects in TypeScript. Note that the function above only works if it’s one line since the return is implicitly done if the arrow function is one line. If it’s more than one line, then we write it with brackets like so:

```typescript
const add = (a: number, b: number) => {  
  return a + b;  
}
```

This way we have to write the `return` statement explicitly. Otherwise, it won’t return a value.

In both examples above, we have the parameter and then the type following each parameter. This is because in TypeScript, if a parameter isn’t followed by a type, then the type will be inferred as having the `any` type, which will be rejected if we have the `noImplicitAny` flag set when we compile the code.

Function Types
==============

To add more checks for the types of the parameters that are passed in and also the return type of the function, we can add a type designation to the function explicitly. We can do this by writing the signature and then adding the fat right arrow, and then appending the return type of the function after that. For example, we can write the following to designate the type of our `add` function:

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

The type designation of the `add` function is:

```typescript
(a: number, b: number) => number
```

in the code above. If we put different types for the parameter than the ones designated by the type we wrote, then the TypeScript compiler will raise an error and refuse to compile the code. For example, if we write:

```typescript
const add: (a: number, b: number) => number =  
  (a: number, b: string) => a + b;
```

Then we get the error:

```typescript
Type '(a: number, b: string) => string' is not assignable to type '(a: number, b: number) => number'.Types of parameters 'b' and 'b' are incompatible.Type 'number' is not assignable to type 'string'.(2322)
```

from the TypeScript compiler. If we don’t write out the type explicitly, TypeScript is still smart enough to infer the type from what’s given on the right side of the assignment operator, so we don’t have to write it out explicitly. It saves us effort from having to type everything to use TypeScript.

Calling a Function
==================

If we are referencing and using a function, then we are **calling** a function.

To call the function, we write:

```typescript
add(1, 2) // 3
```

Since our function returns a value, if we console log the return value of the `add` function:

```typescript
console.log(add(1, 2)) // logs 3
```

We can also assign the return value to a variable:

```typescript
const sum = add(1, 2);  
console.log(sum) // logs 3
```

Part of a Function
==================

All functions have some or all of the following parts:

*   `function` keyword, which is optional
*   the function name, which is optional
*   parentheses — this is required for any function.
*   the parameter inside the parentheses, which is optional
*   opening and closing curly brackets — required for all functions except for single line arrow functions
*   `return` statement, which is optional. If a function doesn’t have a `return` statement, it returns `undefined` . A `return` statement which has nothing following it will end the executing of the function, so it’s handy for controlling the flow of your function.

Using Arguments
===============

As we can see, many functions have arguments. Arguments are data that is passed into a function for computation, so if we have a function call `add(1, 2)`, then 1 and 2 are the arguments.

On the other hand, **parameters** are what we write in the parentheses when we define a function to clarify what we can pass in as arguments.

We do not have to define a function parameters to pass in arguments since we have the `arguments` object in each function. However, it is not recommended since it’s unclear what you want to pass in. We can use the `arguments` for optional things that we want to pass in, however.

For example, if we go back to the `add` function we defined above:

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

`a` and `b` are parameters. When we call it by writing `add(1, 2)`. 1 and 2 are arguments.

We can specify up to 255 parameters when we define a function. However, we shouldn’t do define more than 5 usually since it becomes hard to read.

Pass in Arguments by Value
==========================

There are 2 ways to pass in arguments in TypeScript. One way is to pass in arguments by value. Passing by value means that the arguments passed in are completely separate from the variables you pass in.

The content of the variable is copied into the argument and is completely separate from the original variable if we pass in a variable to a function.

The original variable won’t change even if we change the argument variables that we passed in.

Primitive data types like string, number, boolean, undefined and the `null` object is passed in by value in TypeScript.

For instance, if we have the following code:

```typescript
const a = 1;  
const addOne = (num: number) => num + 1  
const b = addOne(a);  
console.log(b);
```

`a` would still be 1 even after we call `addOne` on `a` since we make a copy of `a` and set it to `num` when we are passing in `a` as the argument for the call to `addOne` .

Pass in Arguments by Reference
==============================

Non-primitive are passed into a function by reference, which means that the reference to the object passed in as the argument is passed into the function. The copy of the content is not made for the argument and the passed in object is modified directly.

For example, if we have the following code:

```typescript
let changeObj = (obj: { foo: string }) => obj.foo = 'bar'  
const obj = {  
  foo: 'baz'  
}  
changeObj(obj);  
console.log(obj); // logs {foo: "bar"}
```

The original `obj` object is defined as `{ foo: 'baz' }`. However, when we pass `obj` into the `changeObj` function, where the passed in `obj` argument is changed in place. The original `obj` object that we passed in is changed. `obj.foo` becomes `'bar'` instead of `'baz'` as it’s originally defined.

Missing Arguments
=================

You do not need to pass in all the arguments into a function in TypeScript. Whatever argument that’s not passed in will have `undefined` set in its place. So if you don’t pass in all the arguments, then you have to check for `undefined` in the arguments so that you don’t get unexpected results. For example, with the `add` function that we had:

```typescript
function add(a, b){  
  return a + b;  
}
```

If we call `add` without the second argument by writing `add(1)`, then we get `NaN` since 1 + `undefined` is not a number.

Default Function Parameter Values
=================================

We can set default function parameters for optional parameters to avoid unexpected results. With the `add` function, if we want to make `b` optional then we can set a default value to `b`. The best way to do it is:

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

In the code above, we set `b` to 1 so that we if we don’t pass in anything for `b`, we automatically get 1 by default for the `b` parameter. So if we run `add(1)` we get 2 instead of `NaN` .

An older, alternative way to do this is to check if the type of the parameter is `undefined` like so:

```typescript
function add(a: number, b: number){  
  if (typeof b === 'undefined'){  
    b = 1;  
  }  
  return a + b;  
}
```

This achieves the same purpose as the first function, but the syntax is clumsier.

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. We will continue to look at TypeScript functions in the next part of this series.