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 has name and email as properties.
  • In line 6, we create the user1 object from a user interface. We only provide the name property.
  • 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 email property in the user1 object.
// create a interface User
interface User{
name:string,
email:string
}
//construct object from interface
let user1:User = {
name : "John"
}
//printing user1 to console
console.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 User
interface User{
name:string,
//marking email as optional variable with question mark
email?:string
}
// construcing object from interface
let user1:User = {
name : "John"
}
//printing out the user1 to console
console.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, John doesn’t have an email, whereas James does.
//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 email field for John is displayed as undefined.
//assume data got from backend
let data = [
{
"name":"John"
},
{
"name":"James",
"email":"James@xyz.com"
}
]
//using foreach loop and arrow functions to display data
data.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 toUpperCase method 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 apply toUpperCase on undefined, since it can only apply this to strings.

//assume data got from backend
let data = [
{
"name":"John"
},
{
"name":"James",
"email":"James@xyz.com"
}
]
//using foreach loop and arrow functions to display data
data.forEach(user=>{
console.log(user.name);
//converting email to uppercase
console.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 backend
let data = [
{
"name":"John"
},
{
"name":"James",
"email":"James@xyz.com"
}
]
//using foreach loop and arrow functions to display data
data.forEach(user=>{
console.log(user.name);
//converting email to uppercase
console.log(user.email?.toUpperCase())
})

Free Resources