How to use a question mark in TypeScript variables
The question mark ? in typescript is used in two ways:
- To mention that a particular variable is optional.
- To pre-check if a member variable is present for an object.
It prevents errors related to undefined or null in a program.
In this shot, we go through the two ways to use the question mark ? in typescript.
Optional variable
If you are familiar with the concept of interfaces in typescript, you might know that we need to use all the properties provided in interface. Otherwise, it throws an error.
In the code snippet, we do the following:
- Define an interface called
User, which hasnameandemailas properties. - In line 6, we create the
user1object from a user interface. We only provide thenameproperty. - When you run the following program, it throws the error
Property 'email' is missing in type '{ name: string; }' but required in type 'User'.. - The error says we are missing the
emailproperty in theuser1object.
// create a interface Userinterface User{name:string,email:string}//construct object from interfacelet user1:User = {name : "John"}//printing user1 to consoleconsole.log(user1)
To resolve the error above, we can use the question mark to mark email as an optional variable.
If you run the following code snippet, you can see that the code is executed without any errors, since we marked email as optional.
//defining interface Userinterface User{name:string,//marking email as optional variable with question markemail?:string}// construcing object from interfacelet user1:User = {name : "John"}//printing out the user1 to consoleconsole.log(user1)
Pre-Check presence of member variable in an object
While developing software, we might come across a situation where we don’t know if a particular member variable is present in the data.
This happens because in document-based databases, the documents do not need to follow the same schema. They can have optional fields.
If that data is sent to the frontend, then we need way to check if a variable is present in that data.
Example
- In the database, the data may be stored like this.
Here,
Johndoesn’t have an email, whereasJamesdoes.
//document 1
{
"name":"John"
},
//document 2
{
"name":"James",
"email":"James@xyz.com"
}
- We get data from the backend to the frontend as an array of objects. If we try to run the code snippet below, we don’t get any errors. But the
emailfield forJohnis displayed asundefined.
//assume data got from backendlet data = [{"name":"John"},{"name":"James","email":"James@xyz.com"}]//using foreach loop and arrow functions to display datadata.forEach(user=>{console.log(user.name);console.log(user.email)})
-
If we try to access any functions on
user.email, the compiler will raise an error. -
In the following code snippet, we use the
toUpperCasemethod on email that the typescript provides to apply on strings. -
Now it will raise the error
Cannot read property 'toUpperCase' of undefined. The error says that it cannot applytoUpperCaseonundefined, since it can only apply this tostrings.
//assume data got from backendlet data = [{"name":"John"},{"name":"James","email":"James@xyz.com"}]//using foreach loop and arrow functions to display datadata.forEach(user=>{console.log(user.name);//converting email to uppercaseconsole.log(user.email.toUpperCase())})
To resolve the error above, use the question mark ? after the email to pre-check.
Note: If the following code snippet does not behave as expected, please copy and paste it in typescript playground
//assume data got from backendlet data = [{"name":"John"},{"name":"James","email":"James@xyz.com"}]//using foreach loop and arrow functions to display datadata.forEach(user=>{console.log(user.name);//converting email to uppercaseconsole.log(user.email?.toUpperCase())})