Writing functions in TypeScript is a fundamental task when describing how to do something. Depending on the context, the functions sometimes need to be referenced or pointed to. In this guide, you will learn two approaches of pointing to a function:
We will work with a code example of a financial transaction.
Let's say that printTransactionDetails()
is a function that takes three parameters: transactionType
of type string
, amount
of type number
, and category
of type string
.
Based on the value of transactionType
, it decides whether a transaction is a credit or a debit and assigns it a value of either Spent
or Earned
.
Finally, it generates a string
and prints on the console before it is returned.
1function printTransactionDetails(transactionType: string, amount: number, category: string): string {
2 let creditOrDebit: string = (transactionType === "debit") ? 'Spent' : 'Earned';
3 let result: string = creditOrDebit + " $" + amount + " in " + category;
4 console.log(result);
5 return result;
6}
Now, let's say you need a variable, printFoodTransaction
, that prints the details of a food transaction.
It has a function type and its signature matches the printTransactionDetails()
function.
You declare it as below.
1let printFoodTransaction: (transactionType: string, amount: number, category: string) => string;
How would you point printFoodTransaction
to the printTransactionDetails()
function?
You can do so by assigning printTransactionDetails
to printFoodTransaction
.
1printFoodTransaction = printTransactionDetails;
To print a food transaction, call the printFoodTransaction
function and pass the values for transactionType
, amount
, and category
.
1printFoodTransaction("debit", 100, "Food")
Make sure your code looks like this.
1function printTransactionDetails(transactionType: string, amount: number, category: string): string {
2 let creditOrDebit: string = (transactionType === "debit") ? 'Spent' : 'Earned';
3 let result: string = creditOrDebit + " $" + amount + " in " + category;
4 console.log(result);
5 return result;
6}
7
8let printFoodTransaction: (transactionType: string, amount: number, category: string) => string;
9printFoodTransaction = printTransactionDetails;
10printFoodTransaction("debit", 100, "Food")
When you run the code in your editor or on the command line, you should see the output below.
1Spent $100 in Food
If you need another variable, say, printUtilityTransaction
, to print transaction details for a utility category, you will need to declare its type again, point it to the printTransactionDetails
function by assigning the value, and call the printUtilityTransaction
function with three arguments.
1let printUtilityTransaction: (transactionType: string, amount: number, category: string) => string;
2printUtilityTransaction = printTransactionDetails;
3printUtilityTransaction("credit", 80, "Utilities");
This time, when you run the code, you should see the output below.
1Spent $100 in Food
2Earned $80 in Utilities
This is one approach of pointing a variable to a function in TypeScript. It is not incorrect, but you can see that there is code duplication when you are describing the type of each variable (printFoodTransaction
, printUtilityTransaction
).
The second approach will tackle this problem and make your code reusable.
Instead of defining the types repeatedly, you can make use of TypeScript interfaces.
Here, transactionPrinter
is an interface that describes the function type. This is like declaring a function with a list of parameters and a return type.
Each parameter requires a name and its corresponding type, which helps to define a contract with the code.
1interface transactionPrinter {
2 (transactionType: string, amount: number, category: string): void;
3}
With the interface defined, the two variables, printFoodTransaction
and printUtilityTransaction
, can now use this function type.
Both printFoodTransaction
and printUtilityTransaction
are of type transactionPrinter
.
You can assign them a function value printTransactionDetails
(of same type) right at the time of declaration.
It makes your code concise, reusable, and easy to read.
1let printFoodTransaction: transactionPrinter = printTransactionDetails;
2printFoodTransaction("debit", 100, "Food");
3
4let printUtilityTransaction: transactionPrinter = printTransactionDetails;
5printUtilityTransaction("credit", 80, "Utilities")
Make sure your code after this refactor looks like this:
1function printTransactionDetails(transactionType: string, amount: number, category: string): string {
2 let creditOrDebit: string = (transactionType === "debit") ? 'Spent' : 'Earned';
3 let result: string = creditOrDebit + " $" + amount + " in " + category;
4 console.log(result);
5 return result;
6}
7
8interface transactionPrinter {
9 (transactionType: string, amount: number, category: string): void;
10}
11
12let printFoodTransaction: transactionPrinter = printTransactionDetails;
13printFoodTransaction("debit", 100, "Food")
14
15let printUtilityTransaction: transactionPrinter = printTransactionDetails;
16printUtilityTransaction("credit", 80, "Utilities");
You should see the output below when you run this code.
1Spent $100 in Food
2Earned $80 in Utilities
In this guide, you learned two approaches for pointing to a function in TypeScript. When working with a small codebase or program, you may choose any one of these approaches. In complex applications, using interfaces to describe the function types enables you to write the code using the DRY (don't repeat yourself) principle. It lets you define contract in the code and perform type checking, especially with JavaScript, which does not support strong typing out of the box.