Unia zdyskryminowana (otagowana) to unia typów obiektów, które wszystkie współdzielą wspólne pole literalne — dyskryminator — którego kompilator używa do rozróżnienia wariantów i bezpiecznego zawężenia.
=
| { : }
| { : ; : }
| { : ; : };
Unia zdyskryminowana (otagowana) to unia typów obiektów, które wszystkie współdzielą wspólne pole literalne — dyskryminator — którego kompilator używa do rozróżnienia wariantów i bezpiecznego zawężenia.
=
| { : }
| { : ; : }
| { : ; : };
Każdy członek ma pole status będące literałem. Sprawdzenie go zawęża typ do dokładnie jednego wariantu, odblokowując pola tego wariantu:
function render(r: Result) {
switch (r.status) {
case "loading": return "...";
case "success": return r.data; // ✅ data exists only here
case "error": return r.message; // ✅ message exists only here
}
}
Jeśli spróbujesz dostępu do r.data w przypadku loading, pojawi się błąd kompilacji — system typów sprawia, że nieprawidłowe kombinacje są niemożliwe do reprezentacji.
function render2(r: Result): string {
switch (r.status) {
case "loading": return "...";
case "success": return r.data;
case "error": return r.message;
default:
const _exhaustive: never = r; // ✅ if you add a variant and forget a case, this errors
return _exhaustive;
}
}
Przypisanie never zmusza cię do obsługi każdego przypadku — dodaj nowy status, a kompilator wskaże każdy switch, który trzeba zaktualizować.
Unii zdyskryminowane to idiomat do modelowania stanów (loading/success/error), zdarzeń/akcji (reducery Redux) i wszelkich danych typu "jeden z kilku kształtów".
Czynią stany nieprawidłowe niemożliwymi do reprezentacji i, dzięki trikowi never, dają ci sprawdzanie wyczerpującości w czasie kompilacji — ogromną wygraną w bezpieczeństwie w porównaniu z luźnym modelowaniem boolean/opcjonalnych pól.