Optional Properties are those properties that are not mandatory. In the example below the person object name is usually mandatory but age may not be. When we create a person object without assigning a value to age the compiler throws age is missing in a type error. To solve this problem, we need to mark the property as optional.
type Person= {
name: string;
age:number;
}
let person:Person= { name:"Eric J. Cerda"}
//Property 'age' is missing in type '{ name: string; }' but required in type 'Person'.
Table of Contents
Creating Optional Properties in TypeScript
To make a specific property optional just add a question mark (?) after the property name
let person : {name:string, age?:number} = { name:"Eric J. Cerda"} type Person= {
name: string;
age?:number;
}
let person:Person = {
name:"Eric J. Cerda",
}
console.log(person.age) //undefinedInterface
interface Person {
name: string;
age?:number;
}
let person:Person = {
name:"Eric J. Cerda",
}
console.log(person.age) //undefinedClass
class Person {
name: string;
age?:number
constructor(name:string) {
this.name=name
}
}
let person= new Person("Eric J. Cerda")
console.log(person.age) //undefinedNote that we did not include age in the class constructor function. If you want to include that then make sure you mark it as an optional parameter
class Person {
name: string;
age?:number //optional
constructor(name:string, age?:number) { //age is optional here
this.name=name
this.age=age
}
}
let person= new Person("Eric J. Cerda")
console.log(person.age) //undefinedOptional Property and Undefined
Adding ? makes age as optional property. Trying to access the value of age returns undefined as expected.
interface Person {
name: string,
age?: number;
}
let person:Person = {name:"Eric J. Cerda"} //ok
console.log(person.age) //undefined
But typescript also allows us to assign undefined value to an optional property although age is of type number.
interface Person {
name: string,
age?: number;
}
let person:Person = {name:"Eric J. Cerda", age:undefined} //okThis is because TypeScript treats every optional property as a union type of undefined and assigned type.
interface Person {
name: string,
age?: number;
}
//The above interface is treated as
interface Person {
name: string,
age?: number|undefined;
}ExactOptionalPropertyTypes Config Option
In the previous section, we showed you that typescript allows us to assign undefined to an optional property.
interface Person {
name: string,
age?: number;
}
let person:Person = {name:"Eric J. Cerda", age:undefined} //okYou can stop that by setting the exactOptionalPropertyTypes to true in the tsconfig.json file under the section compilerOptions. Note that you also need to enable strictNullChecks for the exactOptionalPropertyTypes to work.
{
"compilerOptions": {
"exactOptionalPropertyTypes": true,
"strictNullChecks" : true
},
}With exactOptionalPropertyTypes enabled, the TypeScript compiler throws an error when we try to assign the undefined to the age variable.
interface Person {
name: string,
age?: number;
}
let person:Person = {name:"Eric J. Cerda", age:undefined} //error
//Type '{ name: string; age: undefined; }' is not assignable to type 'Person' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
//Types of property 'age' are incompatible.You can override the behavior by explicitly setting the type as undefined
interface Person {
name: string,
age?: number|undefined;
}
let person:Person = {name:"Eric J. Cerda", age:undefined} Make all properties optional of an existing type
Typescript utility types allow us to construct a new type from an existing type. The Partial utility type is one such utility that takes a type and constructs a new type with all the properties set to optional.
The following is the syntax for converting an existing type to optional.
Partial<exitingType>In this example, the Person interface has all properties marked as required. Assigning it an empty object will result in an error.
interface Person {
name:string;
address:string
age:number
}
let person:Person= {}
//Type '{}' is missing the following properties from type 'Person': name, ageYou can use the Partial<Person> to create a new type with all properties set to optional. Hence it will not result in any compiler error.
interface Person {
name:string;
address:string
age:number
}
let person:Partial<Person>= {} //No error. All Properties are now optional in person objectThe following is one of the use cases for the Partial utility type.
The updatePerson function updates the subset of the properties of person object. The second argument to fields: Partial<Person> create fields object with a type of Person interface with all properties set to optional. This allows us to pass any combination arguments to updatePerson. It also provides a strong type of checking as we cannot pass a non-existing property.
interface Person {
name: string;
address: string;
age: number;
}
function updatePerson(person: Person, fields: Partial<Person>):Person
{
person = { ...person, ...fields }
return person;
}
let person: Person = {
name: "Eric J. Cerda",
address: "Washington",
age: 50,
};
//We can pass anything to fields argument as long as property exists in person interface
//update age & address
person = updatePerson(person, { age: 60, address:"San Francisco" }); //ok
//update address only
person = updatePerson(person, { address:"Washington" }); //ok
//update non existing property city
person = updatePerson(person, { city:"Washington" }); //error
//Argument of type '{ city: string; }' is not assignable to parameter of
//type 'Partial<Person>'.

