How to Type the Function in Typescript. Not Typing✍️, but Type😆

How to Type the Function in Typescript. Not Typing✍️, but Type😆

If you see the long reading time for this article, don't worry 😉. I have written this awesome😎 article with many code examples😃 (with some nice Meme😂 as well); it's not just theory🔥.

So, buckle up🚀. We will begin our incredible journey🛣

get-ready


Functions are the fundamental building blocks🏗 of an application. A function is an action that performs a certain behavior like login the user, showing a list of items, requesting data from the server, and so forth. These actions together compose a system to solve various tasks🔥.

In mathematics, a function is described as an object that produces an output when given an input(meh, why Mathematics here😆). While in programming we have two types✌️ of functions.

  • A function that returns a value,
  • or one that doesn’t return anything.

For instance, if you need the result like the sum of five numbers, we need to return the total value.

And if you need to print out a message to the console, a return type is not necessary.😺

Functions

To begin with, just as in JavaScript, TypeScript functions can be created both as a named function or as an anonymous function🎭.

To quickly recap what these two approaches look like in JavaScript:

// Named function 🤡
function display() {
    console.log("Typescript is Awesome🔥");
}

display(); //Output: Typescript is Awesome🔥

// Anonymous function 🎭
let greeting = function() {
    console.log("You are Awesome😎");
};

greeting(); //Output: You are Awesome😎

Calling a Function ☎️

A function must be called so as to execute it (ofcos 😆). This process is termed as function invocation.

Syntax

Function_name()

The following example illustrates how a function can be invoked −

function test() {   // function definition    
   console.log("function called") 
} 
test()              // function invocation 🔥

On compiling, it will generate the same JavaScript code.

function test() { 
   console.log("function called"); 
} 
test();    // function invocation 🔥

It will produce the following output −

function called

Anonymous Function 🎭

Functions that are not bound to an identifier (function name) are called anonymous functions. These functions are dynamically declared at runtime.

Anonymous functions can accept inputs and return outputs, just as standard functions do😆. An anonymous function is usually not accessible after its initial creation.

Variables can be assigned an anonymous function. Such an expression is called a function expression.

Syntax

var res = function( [arguments] ) { ... } ✅

Example ─ A Simple Anonymous function

var msg = function() { 
   return "hello world";  
} 
console.log(msg())

On compiling, it will generate the same code in JavaScript.😉

It will produce the following output −

hello world

Example ─ Anonymous function with parameters

var res = function(a: number,b: number) { 
   return a*b;  
}; 
console.log(res(12,2))  // 24

The anonymous function returns the product of the values passed to it.


Wuhuu, the main part 🥳


Typing The Function 🤩

Like JavaScript, you use the function keyword to declare a function in TypeScript:

function name(parameter: type, parameter:type,...): returnType {
   // do something
}

Let’s see the following add() function example:

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

In this example, the add() function accepts two✌️ parameters with the number type.

  • When you call the add() function, the TypeScript compiler will check👨‍🏭 each argument passed to the function to ensure that they are numbers.

  • In the add() function example, you can only pass numbers into it, not the values of other types🚨.

The following code will result in an error because it passes two strings instead of two numbers into the add() function:

let sum = add('10', '20');  ❌

Error:

error TS2345: Argument of type '"10"' is not assignable to parameter of type 'number'

The : number after the (parentheses) indicates the return type. The add() function returns a value of the number type in this case.

When a function has a return type, the TypeScript compiler checks👨‍🏭 every return statement against the return type to ensure that the return value is compatible with it👍.

If a function does not return a value, you can use the void type as the return type. The void keyword indicates that the function doesn’t return any value👻.

For example:

function echo(message: string): void {
    console.log(message.toUpperCase());
}

The void prevents🗡 the code inside the function from returning a value and stops the calling code from assigning the result of the function to a variable.

When you do not annotate the return type, TypeScript will try to infer an appropriate type.

For example:

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

In this example, the TypeScript compiler tries to infer the return type of the add() function to the number type, which is expected😆.

More infer stuff on next section😉


Inferring the types 😃

With the example before this, you may notice that the TypeScript compiler can figure out the type even if you only have types on one side of the equation:

// The parameters 'x' and 'y' have the type number
let myAdd = function (x: number, y: number): number {
  return x + y;
};

// myAdd has the full function type
let myAdd2: (baseValue: number, increment: number) => number = function (x, y) {
  return x + y;
};

OPEN THIS LIVE EXAMPLE

Compare the Typescript with Javascript result😎


Lambda Function => ƛ

Lambda refers to anonymous functions in programming. Lambda functions are a concise mechanism to represent anonymous functions. These functions are also called as Arrow functions.

Lambda Function - Anatomy

There are 3 parts to a Lambda function

  • Parameters = A function may optionally have parameters

  • The fat arrow notation/lambda notation (=>) − It is also called as the goes to the operator

  • Statements − represent the function’s instruction set

Lambda Expression

It is an anonymous function expression that points to => a single line of code🚨. Its syntax is as follows −

( [param1, parma2,…param n] )=> statement;

Example: Lambda Expression

var foo = (x: number)=> 10 + x 
console.log(foo(100))      // outputs : 110

The program declares a lambda expression function. The function returns the sum of 10 and the argument passed.

On compiling, it will generate the following JavaScript code.

//Generated by typescript 4.0.2
var foo = (x) => 10 + x;
console.log(foo(100)); //outputs 110

Lambda Statement

Lambda statement is an anonymous function declaration that points to a block of code.🚨 This syntax is used when the function body spans multiple lines. Its syntax is as follows −

( [param1, parma2,…param n] )=> {

   //code block
}

Example: Lambda statement

var foo = (x: number)=> {    
   x = 10 + x 
   console.log(x)   
} 
foo(100) // 110. ✅

The function’s reference is returned and stored in the variable foo.


Awesome 🔥


Optional and Default Parameters 😋

The number of arguments given to a function has to match the number of parameters the function expects.

function buildName(firstName: string, lastName: string) {
  return firstName + " " + lastName;
}

let result1 = buildName("Amirul"); // ❌ error, too few parameters

let result2 = buildName("Amirul", "Asyraf", "Awesome"); 
// ❌ error, too many parameters

let result3 = buildName("Amirul", "Asyraf"); // ✅ ah, just right

OPEN THIS LIVE EXAMPLE FOR BETTER ERROR EXPLANATION

In JavaScript, every parameter is optional😃, and users👨‍💼 may leave them off as they see fit(like optional email field😉). When they do, their value is undefined😬.

We can get this functionality in TypeScript by adding a ? to the end of parameters we want to be optional.

Code please 😑 Ok2

Example: Optional Parameters

function disp_details(id: number,name: string,mail_id?: string) { 
   console.log("ID : ", id); 
   console.log("Name : ", name); 

   if(mail_id!= undefined)  
   console.log("Email Id : ", mail_id); 
}
disp_details(123, "Asyraf");  😎
disp_details(111, "meh", "meh@hey.com");
  • The above example declares a parameterized function. Here, the third parameter, i.e., mail_id is an optional parameter.

  • If an optional parameter is not passed a value during the function call, the parameter’s value is set to undefined😐.

  • The function prints the value of mail_id only if the argument is passed a value.

The above code will produce the following output −

ID : 123 
Name : Asyraf 
ID: 111 
Name : meh 
Email Id : meh@hey.com 👈

In TypeScript, we can also set a value😺 that a parameter will be assigned if the user does not provide one🔥, or if the user passes undefined in its place. These are called default-initialized parameters. I show you in the code version😉.

Example: Default parameters

function calculate_discount(price: number,rate: number = 0.50) { 
   var discount = price * rate; 
   console.log("Discount Amount: ", discount); 
} 
calculate_discount(1000) 
calculate_discount(1000, 0.30)

Its output is as follows −

Discount Amount : 500 🔥
Discount Amount : 300 🔥

another exp 🤩

function buildName(firstName: string, lastName = "Awesome") {
  return firstName + " " + lastName;
}

let result1 = buildName("Amirul"); 
// ✅works correctly now, returns "Amirul Awesome"

let result2 = buildName("Asyraf", undefined); 
// ✅still works, also returns "Asyraf Awesome"

let result3 = buildName("Bob", "Adams", "Sr."); // ❌error, too many parameters

let result4 = buildName("Amirul", "Asyraf"); // ✅ah, just right

OPEN THIS LIVE EXAMPLE FOR BETTER ERROR EXPLANATION


Rest Parameters 🎶

TypeScript introduced rest parameters to accommodate n number of parameters easily🥳.

When the number of parameters that a function will receive is not known🤔 or can vary, we can use rest parameters. In JavaScript, this is achieved with the arguments variable. However, with TypeScript, we can use the rest parameter denoted by the ellipsis ...

Example: Rest Parameters

function addNumbers(...nums: number[]) {  
   var i ;   
   var sum: number = 0; 

   for(i = 0; i < nums.length ; i++) { 
      sum = sum + nums[i]; 
   } 
   console.log("sum of the numbers", sum) 
} 
addNumbers(1,2,3) 
addNumbers(10,10,10,10,10)

another exp 🤩

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}

// employeeName will be "Lucas Samuel Peter MacKinzie"  🔥
let employeeName = buildName("Lucas", "Samuel", "Peter", "MacKinzie");

Remember, rest parameters must come last in the function definition🚨, otherwise the TypeScript compiler will show an error😆.

The following is not valid.

function Greet(...names: string[], greeting: string) {  // ❌Compiler Error
    return greeting + " " + names.join(", ") + "!";
}

OPEN THIS LIVE PLAYGROUND TO SEE ERROR


Arrow Function =>

Fat arrow notations are used for anonymous functions i.e for function expressions. They are also called lambda functions in other languages.

In this section, no more Theory😆 because I have explained that in the Lambda and Anonymous Function section...

So, more code examples🤩

Syntax:

(param1, param2, ..., paramN) => expression

Example: Fat Arrow Function

let sum = (x: number, y: number): number => {
    return x + y;
}

sum(10, 20); //returns 30 ✅

Example: Parameterless Arrow Function

let Print = () => console.log("Hello TypeScript");

Print(); // Output: Hello TypeScript ✅

Furthermore, if the function body consists of only one statement then no need for the {curly brackets} and the return keyword, as shown below.

let sum = (x: number, y: number) => x + y;

sum(3, 4); //returns 7 ✅

A class can include an arrow function as a property, as shown below.

Example: Arrow Function in Class Copy
class Employee {
    empCode: number;
    empName: string;

    constructor(code: number, name: string) {
        this.empName = name;
        this.empCode = code;
    }

    display = () => console.log(this.empCode +' ' + this.empName)
}
let emp = new Employee(1, 'Asyraf'); 🤓
emp.display();

another Arrow function in a class example

Muahahaha😂

class Student {  
    studCode: number;  
    studName: string;  
    constructor(code: number, name: string) {  
            this.studName = name;  
            this.studCode = code;  
    }  
    showDetail = () => console.log("Student Code: " + this.studCode + '\nStudent Name: ' + this.studName)  
}  
let stud = new Student(101, 'Asyraf Awesome'); 🔥
stud.showDetail();

Output

Student Code: 101
Name: Asyraf Awesome 🔥

The Function Constructor

TypeScript also supports defining a function with the built-in JavaScript constructor called Function (). 🤩

Syntax

var res = new Function( [arguments] ) { ... }.

Example

var myFunction = new Function("a", "b", "return a * b"); 
var x = myFunction(4, 3); 
console.log(x); // 12

The new Function() is a call to the constructor which in turn creates and returns a function reference.🔥

On compiling, it will generate the same code in JavaScript.


Function Overloads

TypeScript provides the concept of function overloading. You can have multiple functions with the same name but different parameter types and return type. However, the number of parameters should be the same.

function add(a: string, b: string): string;

function add(a: number, b: number): number;

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

add("Hello ", "Steve"); // returns "Hello Steve" 
add(10, 20); // returns 30

In the above example, we have the same function add() with two function declarations and one function implementation. The first signature has two parameters of type string, whereas the second signature has two parameters of the type number.

The last function should have the function implementation. Since the return type can be either string or number as per the first two function declarations, we must use compatible parameters and return type as any in the function definition.

It is a useful concept that can create abstract layers when dealing with functions with many behaviors🔥.

Let’s see an example of overload parameter🤩:

// Create overloads
function runEngines(engine: { engine1: boolean; engine2: boolean });
function runEngines(engines: number);
function runEngines(engines: boolean);
function runEngines(x): any {
    // If argument is number
    if (typeof x === "number") {
        console.log(`Run all ${x}`);
    }
    // If argument is an object
    if (typeof x === "object") {
        console.log(`Run eng1: ${x.engine1}, eng2: ${x.engine2}`);
    }
    // If argument is a boolean
    if (typeof x === "boolean") {
        let msg = x ? "Start all engines" : "Stop all engines";
        console.log(msg);
    }
}
// Invoke function
runEngines({ engine1: true, engine2: false }); // Output: Run eng1: true, eng2: false
runEngines(4); // Output: 4
runEngines(true); // Output Start all engines

As shown in the example above, the function runEngines() use the typeof keyword to check the argument type to define what operation to execute. Notice that the function function runEngines(x): any must be defined last because it’s a universal function🌎 that represents all possibilities defined in the functions above😎.

Another Cool Example🤩

// Overloads
function padding(all: number);
function padding(topAndBottom: number, leftAndRight: number);
function padding(top: number, right: number, bottom: number, left: number);

// Actual implementation that is a true representation of all the cases the function body needs to handle
function padding(a: number, b?: number, c?: number, d?: number) {
    if (b === undefined && c === undefined && d === undefined) {
        b = c = d = a;
    }
    else if (c === undefined && d === undefined) {
        c = a;
        d = b;
    }
    return {
        top: a,
        right: b,
        bottom: c,
        left: d
    };
}

Here the first three function headers are available as valid calls to padding:

padding(1); // Okay: allpadding(1,1); // Okay: topAndBottom, leftAndRight ✅

padding(1,1,1,1); // Okay: top, right, bottom, left ✅

padding(1,1,1); // ❌ Error: Not a part of the available overloads

The Function/Method overloading is allowed when:

  • The function name is the same
  • The number of parameters is different🚨 in each overloaded function.
  • The number of parameters is the same🚨, and their type is different🚨.
  • All overloads function must have the same return type.

The last part 😍


This keyword in Function

I will not explain it in this article🙏 because it makes this article too long🚀 to read tho😆.

Also, the explanation about this keyword is too detailed🥺 to explain in this awesome article😃.

I will give you the link that you can learn about it awesomely👍

This keyword in Function

you will learn ;

  • this
  • this and arrow functions
  • this parameters
  • this parameters in callbacks

    Great 🤜🤛


Finish 🏁 finish done

Wuhuuu🥳

Thanks for finishing it 🙌

You're Awesome 😎

Bookmark and Share it 🤟


Another cool resources🤘

Muahhaha😂

note : I'm sorry🙏 for the long article as I want you to understand better and triple better than me🔥