While you are learning TypeScript and reading someone else’s code, you find there is the following declaration in a file of a project:
interface User {
id: string;
firstName: string;
middleName?: string;
lastName: string;
}
Why does the middleName property is followed by a question mark ?: ?
Table of Contents
What does ?: mean in TypeScript?
Using a question mark followed by a colon (?:) means a property is optional. That said, a property can either have a value based on the type defined or its value can be undefined.
Similar to using two types where one type is undefined
Another way to think about using a question mark with a colon (?:) is to define two types to a property where one of them is undefined. Hence, if we make a small modification to the User interface, the middleName property will have a type definition of string | undefined.
interface User {
id: string;
firstName: string;
middleName: string | undefined;
lastName: string;
}
Difference between ?: and using two types where one type is undefined
There is one problem with using middleName: string | undefined; instead of middleName?: string;. The middleName property is no longer optional.
Depending on the IDE you use, you can get immediate feedback saying the property is required. For example, try adding the following code, which creates an admin variable with a type of User that doesn’t have a middleName:
interface User {
id: string;
firstName: string;
middleName: string | undefined;
lastName: string;
}
const admin: User = {
id: '92d4549c-ebe1-49b4-b113-26cf00d204bc',
firstName: 'Andres',
lastName: 'Reales'
};
You should notice the IDE displays the following error
Property 'middleName' is missing in type '{ id: string; firstName: string; lastName: string; }' but required in type 'User'.(2741)
right underneath the admin variable:

Unless the admin has a middleName value assigned, the code will not run due to compilation errors. In this case, using the question mark with a colon (?:) is a better alternative as it will make middleName property optional. In that way, we can update the type definition back to string only.
interface User {
id: string;
firstName: string;
middleName?: string;
lastName: string;
}
const admin: User = {
id: '92d4549c-ebe1-49b4-b113-26cf00d204bc',
firstName: 'Andres',
lastName: 'Reales',
};
As you notice, the error disappears and the code will compile.

Using ?: with undefined as type definition
It is possible to use ?: with an undefined type. If you remember the example where we used string | undefined type definition for the middleName, we can add the ?: and keep the undefined type.
interface User {
id: string;
firstName: string;
middleName?: string | undefined;
lastName: string;
}
While there are no errors with this interface definition, it is inferred the property value could undefined without explicitly defining the property type as undefined. In case the middleName property doesn’t get a value, by default, its value will be undefined.
interface User {
id: string;
firstName: string;
middleName?: string;
lastName: string;
}
const admin: User = {
id: '92d4549c-ebe1-49b4-b113-26cf00d204bc',
firstName: 'Andres',
lastName: 'Reales',
};
console.log(admin.middleName); // it will log: undefined
Question mark ?: is not only used with interfaces
In the initial example, we noticed the usage of the question mark with a colon (?:) when defining the properties of an interface. In a similar way, we can do so this when defining a class.
class Car {
id: string;
brand: string;
model: string;
year: number;
price?: number;
}
This gives the flexibility to not having the need to provide values to all properties of a class.
We can also define optional parameters when creating functions in TypeScript.
function buyGift(itemId: string, accountId: string, message?: string) {
const item = getItem(itemId);
pay(item.price, accountId);
if (message) {
sendMessage(message);
}
}
buyGift('item id', 'account id');
Notice how we didn’t need to pass all three arguments to trigger the buyGift function. Instead, we provided only the necessary arguments.
This is a big benefit in TypeScript when compared to defining functions in JavaScript as all of the parameters in JavaScript are optional, even if the logic inside the function requires them, while in TypeScript you have to explicitly add the question mark ?: to make parameters optional.
Using strictNullChecks TypeScript Compiler Option
If you don’t know, you can define TypeScript compiler options inside a tsconfig.json file. This file might have a structure like this:
{
"compilerOptions": {
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true
}
}
Defining compiler options inside the compilerOptions property of the tsconfig.json file is a good way to enforce a set of rules in the code.
For instance, we know that by defining an interface with an optional property such as middleName?: string:
interface User {
id: string;
firstName: string;
middleName?: string;
lastName: string;
}
The possible values of middleName should be either undefined or a string value. However, what if I show you I can define the value of null to the middleName property like in the next code snippet?
const admin: User = {
id: '92d4549c-ebe1-49b4-b113-26cf00d204bc',
firstName: 'Andres',
lastName: 'Reales',
middleName: null
};
While this is not correct, TypeScript might or not display an error. If you are not getting an error, it is because you don’t have strictNullChecks compiler option. For the purposes of understanding this concept, go ahead and add strictNullChecks with a value of true in the TypeScript compiler options and save the changes made in your tsconfig.json file.
{
"compilerOptions": {
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true,
"strictNullChecks": true
}
}
If you go back to the code, you should see TypeScript displaying the following error:
Type 'null' is not assignable to type 'string | undefined'.(2322)index.ts(4, 3): The expected type comes from property 'middleName' which is declared here on type 'User'(property) User.middleName?: string | undefined
in the property middleName of the admin object.

In that way, we prevent potential logic issues from happening during runtime.
Conclusion
In this article, you learned what it means to use the question mark followed by a colon ?: in TypeScript as well as the difference between using ?: and using undefined type without the question mark. Also, you can enable strictNullChecks compiler option to prevent assigning null values to a property that is an option, unless null is one of the type definitions of the property.
Interested in Reading More About TypeScript?
I wrote other TypeScript articles, and I thought you might be interested in reading some of them since you are reading this.
- 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
Did you like this article?
Share your thoughts by replying on Twitter of Become A Better Programmer or to personal my Twitter account.