The example doesn't work properly because selected is bound with [value]="topping.id", but the logic uses selected.id which doesn't exist except on startup because you are initializing selected with a topping object. 
Also, the logic [disabled]="topping.id < selected.id" is possibly flawed because it also disables inprogress when close is selected  - you might want that - I'm not sure - but you only said you wanted to disable open when inprogress is selected.
Either use [value]="topping":
<mat-form-field>
    <mat-select placeholder="Toppings" [(ngModel)]="selected" [formControl]="toppings">
        <mat-option *ngFor="let topping of list" [value]="topping" [disabled]="selected.id === '2' && topping.id === '1'">{{topping.name}}</mat-option>
    </mat-select>
</mat-form-field>
Or change the logic and initialization of selected:
selected: any =  '2';
<mat-form-field>
    <mat-select placeholder="Toppings" [(ngModel)]="selected" [formControl]="toppings">
        <mat-option *ngFor="let topping of list" [value]="topping.id" [disabled]="selected === '2' && topping.id === '1'">{{topping.name}}</mat-option>
    </mat-select>
</mat-form-field>
Update for Angular v6/7 and later
Use [(value)] instead of [(ngModel)]. Support for using the ngModel input property and ngModelChange event with reactive form directives has been deprecated in Angular v6 and is removed in Angular v7.