Is it essential to specify null in both the constructor and the field definition?
Absolutely, but this requirement stems from how the managerOf
property is defined. It all hinges on the type of the property, and Typescript enforces that everything aligns accordingly.
You initially declared:
private managerOf: User;
This means only a User
can be assigned to the managerOf
property. As null
is not a User
, it is not permitted.
Moving on to the constructor:
class User {
private name: string;
private managerOf: User;
constructor(name: string, managerOf: User) {
this.name = name;
this.managerOf = managerOf;
}
}
new User('qwerty', null) // error
Here, you cannot pass in null
because the constructor does not accept null
. To resolve this issue:
class User {
private name: string;
private managerOf: User;
constructor(name: string, managerOf: User | null) {
this.name = name;
this.managerOf = managerOf; // error
}
}
new User('qwerty', null) // fine
Now, you are able to provide null
as an argument for the constructor. However, null
still does not match the allowed types for the managerOf
property, resulting in an error upon assignment.
Therefore, allowing null
in the managerOf
property necessitates including it in the type definition.
The constructor parameter for managerOf
is completely independent from the actual managerOf
property of the instances of the class. Type safety is enforced by Typescript when assigning one to the other.
How could Typescript know that you want to avoid something like this?
class User {
private name: string,
private managerOf: User
constructor(name: string, managerOf: User | null) {
this.name = name
this.managerOf = managerOf || defaultManager
}
}
const jerry = new User("Jerry", null);
jerry.managerOf.name // returns the default name
In this scenario, you allow null
in the constructor, assign a default value to the property if it is null. Cases like these justify the need to specify it in "both" places.
An alternative shorthand method exists for handling this situation:
class User {
constructor(
private name: string,
private managerOf: User | null
) {}
}
new User('qwerty', null) // fine
With this syntax, a constructor argument can be directly assigned to an instance property, effectively declaring it only once.
Check out playground