Essentials of TypeScript Functions
In the previous article
of this series you learned about TypeScript variables and their data types. A
common JavaScript construct is function. And TypeScript has some interesting
features to offer when it comes to creating functions. Specifically this article
covers function return types, optional parameters, default parameters, rest
parameters, and callbacks.
So, let's get going. I am going to use a variation of the temperature
convertor example in this article. So make sure that you are familiar with it
from the previous part
of this series.
Begin by adding Functions.ts and Functions.html files into the TypeScript
folder. You will write the following TypeScript inside Functions.ts file.
Indicate function return type
Earlier you create the convert() function that takes a numeric value and
ConversionType parameters as the input. However, the function didn't return any
value to the caller. Here, I am going to split the convert() function into three
independent functions namely convertToCelsius(), convertToFahrenheit(), and
showResult().
The convertToCelsius() function is shown below:
function convertToCelsius(value: number): number {
let tempInC: number;
tempInC = (value - 32) * 5 / 9;
return tempInC;
}
The convertToCelsius() function takes a numeric input as before and returns
the temperature value in Celsius. Notice the code marked in bold letters. After
the function parameter list there is colon (:) followed by the return type of
the function. The return type could be any valid data type (inbuilt or custom)
including void.
Inside, the code applies a formula that converts a temperature value to
Celsius and stores the result into tempInC local variable. This value is then
returned from the function. You could have done all of this into a single line
of code but here deliberately I am using a bit verbose code for clear
understanding.
The convertToFahrenheit() function looks similar except that it converts a
temperature value into Fahrenheit.
function convertToFahrenheit(value: number): number {
let tempInF: number;
tempInF = value * 9 / 5 + 32;
return tempInF;
}
You might want to output the result of the conversion on to the page. The
showResult() function does that and is shown below:
let showResult = function (result: number): void {
document.getElementById("msg").innerHTML
= "<h2>Result : " + result + "</h2>";
}
This function uses an alternate approach to defining a function. Instead of
creating a named function such as convertToCelsius() and convertToFahrenheit(),
it creates an anonymous function that accepts a numeric parameter and returns
nothing (void). Inside, the code grabs the msg <div> element and sets its
innerHTML property to the result.
This anonymous function can be called using the showResult variable like
this:
showResult(100);
Once these three functions are ready you can modify the convert() function to
use them. The modified convert() function is shown below:
function convert(value: number,
conversionType: ConversionType): void {
let result: number;
if (conversionType ==
ConversionType.CelsiusToFahrenheit) {
result = convertToCelsius(value);
}
else {
result =
convertToFahrenheit(value);
}
showResult(result);
}
This code is quite straightforward and hence I won't go into more details.
To test the code you wrote so far, add this markup to the Functions.html
file.
<body onload="DoWork()">
<div id="msg"></div>
<script src="/TypeScript/Output/Functions.js">
</script>
</body>
The DoWork() function needs to added to the Functions.ts and is shown below:
function DoWork() {
convert(100, ConversionType.CelsiusToFahrenheit);
}
And here is a sample output:
Optional Parameters
The convert() function takes two required parameters - numeric value and
ConversionType. If you want to skip setting the ConversionType explicitly, you
can make it an optional parameter. Once you mark it as an optional parameter you
are not required to supply its value while calling the convert() function. Since
this is now an optional parameter, you must take into account a possibility of
missing ConversionType in your code. You might use some default value in case
ConversionType is missing or change the course of execution as needed.
The following code shows how a function parameter can be marked optional.
function convert(value: number,
conversionType?: ConversionType): void {
}
Notice that conversionType parameter is now suffixed with ? character. This
indicates that it's an optional parameter.
To account for this missing value you can perform the following check in your
code:
if (typeof conversionType === 'undefined') {
conversionType = ConversionType
.CelsiusToFahrenheit;
}
If you don't pass a ConversionType while calling the convert() function, the
value of conversionType parameter will be undefined. And you assume the
conversion type to be CelsiusToFahrenheit.
The completed convert() is shown below:
function convert(value: number,
conversionType?: ConversionType): void {
let result: number;
if (typeof conversionType === 'undefined') {
conversionType =
ConversionType.CelsiusToFahrenheit;
}
if (conversionType ==
ConversionType.CelsiusToFahrenheit) {
result = convertToCelsius(value);
}
else {
result = convertToFahrenheit(value);
}
showResult(result);
}
Optional parameters must appear at the end of the parameter list in a
function signature.
You can call the convert() function like this:
function DoWork() {
convert(100);
}
As you can see, this time you haven't passed a ConversionType.
Default parameters
Many a times optional parameters have some default value. In the parameter is
missing this default value is used. One way to accomplish this is to use
optional parameters as discussed above. An easy approach is to assign a default
value. The following code shows the convert() function that uses a default value
for ConversionType.
function convert(value: number, conversionType:
ConversionType = ConversionType.CelsiusToFahrenheit)
: void {
let result: number;
if (conversionType ==
ConversionType.CelsiusToFahrenheit) {
result = convertToCelsius(value);
}
else {
result = convertToFahrenheit(value);
}
showResult(result);
}
As you can see, conversionType is no longer an optional parameter but has a
default value assigned to it. If you don't supply a ConversionType while calling
convert() then this default value will be used. Since a default value is
specified in the function signature itself, you don't need the "undefined" check
inside the code.
Rest parameters
At times you are unaware of the number of parameters to be passed to a
function. For example, so far the current() function is converting just one
temperature value. What if you want to pass 2 or more values. Additionally, you
might not know how many values are to be passed. Sometimes 2, sometimes 3, and
sometimes 5. In such cases Rest parameters come handy. They indicate "rest" of
the parameters being passed to the function. If you are familiar with C# param
array then Rest parameters should look familiar to you.
This is how convert() can be modified to use Rest parameters.
function convert(conversionType: ConversionType,
...values: number[]): number[] {
let results: number[] = new Array();
for (let item in values) {
if (conversionType ==
ConversionType.CelsiusToFahrenheit) {
results.push(
convertToFahrenheit(values[item]));
}
else {
results.push(
convertToCelsius(values[item]));
}
}
showResults(results);
)
Notice the code shown in bold letters. This is how you indicate a Rest
parameter. Since Rest parameters must appear at the end of a function signature,
ConversionType is made the first parameter and ...values as the second
parameter. The varying number of values passed while calling convert() are
captured as a number array (since a temperature value is number). The three dots
syntax marks value to be a Rest parameter.
Inside, the code creates a new numeric array to store the converted values.
This array is initialized using Array object.
A for..in loop of TypeScript iterates through the values array. Every
iteration converts a temperature value depending on ConversionType and pushes it
to the results array using push() method.
To display the converted values on the page, you need showResults() function
that accepts the results array. This function is shown below:
let showResults = function
(results: number[]) {
for (let item in results) {
document.getElementById
("msg").innerHTML +=
"<h2>" + results[item] + "</h2>";
}
}
This code iterates through all the results and appends them to the msg <div>
element.
You can now call convert() like this:
function DoWork() {
convert(ConversionType.CelsiusToFahrenheit,
100,200,300);
}
And here is the output:
Callback functions
Function parameters are not restricted to primitive data types or complex
types. You can also pass a function as a parameter to another function. In
JavaScript this is often done while using callback functions. TypeScript
provides a better and strongly typed approach to passing such callback
functions. Let's see how.
Suppose you want to accept a third parameter to the convert() function that
accepts a callback function. This callback function is executed once the
temperature conversion is done. A benefit of this approach is that you are not
tied to showResult() function to display the result. You can decide what should
happen upon calculating a temperature value while calling the convert() method.
At times you may display it inside <div> element, at times you might display it
in a popup, and at some other times you might pass the result to another
function for further processing.
The modified signature of convert() is shown below:
function convert(value: number,
conversionType: ConversionType,
callback: (result: number) => void) {
let result: number;
if (conversionType == ConversionType.
CelsiusToFahrenheit) {
result = convertToFahrenheit(value);
}
else {
result = convertToCelsius(value);
}
callback(result);
}
Notice the code shown in bold letters. The convert() function now has a third
parameter called callback. Since this parameter is supposed to be a function,
its "type" is a function. And the function signature is indicated using what is
known as an arrow function. Here, the code indicates that the callback function
should be a function that takes one numeric parameter and returns void.
Inside, after performing the necessary temperature conversion, the code
invokes the callback function by passing the result value to it.
To call this version of convert() you can write the following code:
function DoWork() {
convert(100, ConversionType.CelsiusToFahrenheit,
(result) => {
document.getElementById
("msg").innerHTML =
"<h2>Result : " + result + "</h2>";
});
Notice how the callback function is specified as an arrow function. You could
have also used the following approach to call convert().
let callback = function(result:number):void {
document.getElementById("msg").
innerHTML = "<h2>Result : " + result + "</h2>";
}
convert(100, ConversionType.CelsiusToFahrenheit,
callback);
You can read more about TypeScript functions in the official documentation
here.
You can also watch the companion video to this article that shows everything
discussed in the article:
That's it for now! Keep coding!!