Passing optional and default parameters in a function is a common practice used by programmers developing not only in TypeScript or JavaScript but any programming language. In this tutorial, we are going to explain how to use them in TypeScript, compare the TypeScript syntax with the JavaScript syntax, as well as share some best practices when using default parameters.
Table of Contents
How to Use Optional Parameters in TypeScript
If we want to use optional parameters in TypeScript, we can enable it by adding a question mark ?
at the end of each parameter of a function. Let’s look at the following example to make things clear.
function updateInfo(id: string, email: string, updatedBy?: string) {
// check if the email provided is empty
if (!email) throw new Error('It must provide an email');
const db = mysql.createConnection({
host: "localhost",
user: "yourusername",
password: "yourpassword",
database: "mydb"
});
db.connect(function(err) {
if (err) throw err;
// it must update the user's email
let sql = `
UPDATE users
SET
email = ?
`;
const queryParams = [email];
// check if value provided in optional parameter
if (updatedBy) {
sql += `, updated_by = ?`;
queryParams.push(updatedBy);
}
// update only one record based on id provided
sql += `WHERE id = ?`;
queryParams.push(id);
db.query(sql, queryParams, function (err, result) {
if (err) throw err;
console.log(result.affectedRows + " record(s) updated");
});
});
}
Notice the parameters of the updatedInfo
function in the previous code snippet. It accepts three parameters: id
, firstName
, and updatedBy
. Out of the three parameters, only updatedBy
has the question mark ?
at the end of the parameters’ definition. Hence, this means updatedBy
is the only optional parameter in this function.
Why Using Optional Parameters
Having optional parameters is a neat functionality that allows developers to avoid passing all of the parameters defined in a function. This makes it easier for the logic calling a function to provide only the necessary values required for the main logic of a function to be executed.
On the other hand, it allows a function to hide extra layers of logic complexity. If we revisit the previous snippet of code, the main functionality of the updateInfo
function is to update a user’s email. Notice how it is possible to update the updated_by
field inside updateInfo
when the updatedBy
parameter is provided, even though it is not considered a critical part of logic.
Also, notice how the code becomes more complex when adding the logic to update the updated_by
field. If we decide to remove the logic to update the updated_by
field, which would make the updateBy
parameter unnecessary, the updateInfo
function would be much simpler and with fewer lines of code as well.
function updateInfo(id: string, email: string) {
// check if the email provided is empty
if (!email) throw new Error('It must provide an email');
const db = mysql.createConnection({
host: "localhost",
user: "yourusername",
password: "yourpassword",
database: "mydb"
});
db.connect(function(err) {
if (err) throw err;
const sql = `
UPDATE users
SET email = ?
WHERE id = ?
`;
const queryParams = [email , id];
db.query(sql, queryParams, function (err, result) {
if (err) throw err;
console.log(result.affectedRows + " record(s) updated");
});
});
}
Comparing JavaScript and TypeScript Usage of Optional Parameters
The functionality of passing optional parameters in both JavaScript and TypeScript is the same. However, their implementation is different. In JavaScript, all parameters are considered optional by default, even if the internal logic of a function depends on some parameters. Let’s look at the following example:
function getCar(id) {
const db = mysql.createConnection({
host: "localhost",
user: "yourusername",
password: "yourpassword",
database: "mydb"
});
return new Promise(function(resolve, reject) {
db.connect(function(err) {
if (err) reject(err);
const sql = `
SELECT * FROM users
WHERE id = ?
`;
const queryParams = [ id];
db.query(sql, queryParams, function (err, result) {
if (err) reject(err);
resolve(result);
});
});
})
}
// it will fail during runtime in JavaScript
getCar();
The getCar
function depends on the id
parameter to fetch the correct car from the database, if not provided, the function most likely will fail during runtime.
This is a problem in JavaScript as errors cannot be prevented much sooner prior to deploying code to production environments. In other cases, it would create the need for JavaScript developers to pass all parameters even if some are truly optional, for the sake of avoiding errors in runtime due to the lack of parameter values.
TypeScript aims to solve this issue by making all parameters defined in a function required unless the parameter is followed by a question mark ?
. Also, it will allow getting much sooner feedback to programmers as code will fail in build time instead of runtime.
// it will fail during build in TypeScript
getCar();
How to Use Default Parameters in TypeScript
If we want to set a default parameter in TypeScript, the parameter must have in the end the equal sign (=
) followed by the default value. Let’s look at an example of this implementation:
function logHello(requiredParamater: string, defaultParameter: string = 'foobar') {
console.log(`${requiredParamater} ${defaultParameter}`);
}
logHello('hello'); // result: 'hello foobar'
logHello('hello', 'andres'); // result: 'hello andres'
Notice how the logHello
function can be called with or without defaultParameter
.
Why Using Default Parameters
Using default parameters allow you to not worry about providing values of parameters that are repetitive when calling a function in different scenarios while also avoiding to provide all parameters to trigger a function.
If we look back at the first definition of the updateInfo
, we defined an optional updatedBy
parameter to update the updated_by
field of a record whenever the parameter is provided. However, that is not a typical implementation of an update functionality as under real projects we need to track the last user who made updates to a record. Hence, we are going to modify the updateInfo
function to always update the updated_by
regardless if the updatedBy
is provided during its execution.
function updateInfo(id: string, email: string, updatedBy: string = 'admin') {
// check if the email provided is empty
if (!email) throw new Error('It must provide an email');
const db = mysql.createConnection({
host: "localhost",
user: "yourusername",
password: "yourpassword",
database: "mydb"
});
db.connect(function(err) {
if (err) throw err;
const sql = `
UPDATE users
SET
email = ?,
updated_by = ?
WHERE id = ?
`;
const queryParams = [email, updatedBy, id];
db.query(sql, queryParams, function (err, result) {
if (err) throw err;
console.log(result.affectedRows + " record(s) updated");
});
});
}
Now, everytime any logic of code is calling the updateInfo
without the updatedBy
parameter, the updated_by
field of the record will default to 'admin'
.
updateInfo('123id', '[email protected]');
This gives us the flexibility to also set the updated_by
field of a record to a different value besides 'admin'
whenever it is considered necessary.
updateInfo('123id', '[email protected]', 'andres');
Best Practice When Using Default Parameters
It is recommended to define default parameters after all required parameters are defined. Otherwise, you will be forced to provide a value to the parameter with a default value as other parameters have required values.
Let’s modify the position of the parameters of the logHello
function to see how this affects calling this function.
function logHello(defaultParameter: string = 'foobar', requiredParamater: string) {
console.log(`${requiredParamater} ${defaultParameter});
}
// we no longer can call the logHello function passing only one parameter
logHello('andres'); // this will fail during build time
// we are forced to provide the two parameters even if one of them has already an
// default value
logHello('andres', 'hello'); // result: 'hello andres'
Notice how defining defaultParameter
prior to defining requiredParameter
will force us to provide the two parameters when calling the logHello
function. Therefore, we won’t be able to avoid passing a value to defaultParameter
.
More TypeScript Tips!
There is a list of TypeScript tips you might be interested in checking out.
- TypeScript | The Unknown Type Guide
- TypeScript | Organizing and Storing Types and Interfaces
- TypeScript | Double Question Marks (??) – What it Means
- TypeScript | Objects with Unknown Keys and Known Values
- TypeScript | Union Types – Defining Multiple Types
- TypeScript | Declare an Empty Object for a Typed Variable
- TypeScript | Union Types vs Enums
- TypeScript | Convert Enums to Arrays
Conclusion
Using optional and default parameters is a handy functionality to hide additional and repetitive complex logic of code in a function. Using optional parameters in JavaScript differs from how it is used in TypeScript. However, it is recommended to assign default and optional parameters only after required parameters are defined in a function regardless of whether you are using JavaScript or TypeScript.
Did you like this article?
Share your thoughts by replying on Twitter of Become A Better Programmer or to personal my Twitter account.