Have you considered why they must be null? I personally find it more confusing to have an empty option.
You can experiment with the StackBlitz to observe how it behaves when initialized as an empty array versus when it is linked to an array with a single null item. I believe the user experience is better when the mat-select is linked to an empty array. The mat-label is located inside the select box, making it easy to understand the type of data in the select. Moreover, clicking it will not display any options since there are none. With a null value, the dropdown opens with a blank item.
I don't see anything wrong with the code you shared.
Edit:
You can bind the mat-select item with an object and utilize a display property to show the text and a value property to link to the actual value.
Suppose you have an interface like this:
export interface DateSelectItem
{
value: number;
label: string;
}
let dates: DateSelectItem[] = [
{
value: -1,
label: "None"
}
];
selectedDate: DateSelectItem;
In the template:
<mat-form-field>
<mat-label>Date</mat-label>
<mat-select [(ngModel)]="selectedDate">
<mat-option *ngFor="let date of dates" [value]="date">
{{date.label}}
</mat-option>
</mat-select>
</mat-form-field>
You can use plain strings and convert them between their numerical equivalents.
Alternatively, by using an object, you can utilize the label property to display something other than the value.
EDIT: Modified StackBlitz
You may need to adjust the business logic regarding what you want the selected date to appear if the user chooses 'None' for the day-of-the-month.
Revised StackBlitz