programowanieFrontend developer

Jak działa mechanizm dostępu do opcjonalnych właściwości (Optional Properties) w TypeScript, z jakimi problemami można się spotkać i jak ich uniknąć?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Opcjonalne właściwości w TypeScript oznaczane są znakiem zapytania (?) po nazwie właściwości. Oznacza to, że właściwość może być albo określona, albo nieobecna w obiekcie. Jest to wygodne przy opisywaniu struktur, gdzie nie wszystkie pola są obowiązkowe.

Przykład:

interface User { id: number; name?: string; } const u1: User = { id: 1 }; // OK const u2: User = { id: 2, name: 'Ivan' }; // OK

Szczegóły:

  • Opcjonalna właściwość może być nie tylko undefined, ale także całkowicie nieobecna w obiekcie.
  • Sprawdzanie istnienia wartości (np. if (user.name)) nie odróżnia undefined od braku.
  • Częsty błąd — nie uwzględnianie, że właściwość może być undefined, i odwoływanie się do metod/właściwości bez sprawdzenia.

Aby się zabezpieczyć:

  • Używaj sprawdzeń na undefined:
if (user.name !== undefined) { console.log(user.name.toUpperCase()); }
  • Można używać operatora opcjonalnego łańcucha:
console.log(user.name?.toUpperCase());

Pytanie z podstępem.

Jeśli obiekt ma opisany interfejs { foo?: string }, czy zawsze właściwość foo może być tylko ciągiem lub undefined? Czy można w nim zapisać, na przykład, wartość null?

Błędna odpowiedź:

  • "Opcjonalna właściwość może być tylko ciągiem lub undefined, inne wartości są niedopuszczalne."

Prawidłowa odpowiedź:

  • W rzeczywistości, jeśli jawnie przypisać null, TypeScript to dopuszcza, ale tylko jeśli typ jest rozszerzony do string | null. Domyślnie tylko string lub undefined.
  • Przykład:
interface A { foo?: string } let x: A = { foo: null }; // Błąd!

Przykłady rzeczywistych błędów z powodu nieznajomości szczegółów tematu.


Historia

W dużym projekcie część obiektów przychodziła z serwera bez niektórych opcjonalnych pól. Programista bezpośrednio wywoływał metody na tych właściwościach (np. toLowerCase()), co prowadziło do błędów w czasie działania, jeśli pole było nieobecne. Aby rozwiązać problem, zespół wdrożył ścisłe kontrole i zasady lintera dotyczące dostępu do opcjonalnych pól.


Historia

W wyrażeniach logicznych pomylono obecność właściwości z jej prawdziwością: if (user.email) nie działało dla pustych ciągów, chociaż właściwość była określona. Pojawił się błąd, z powodu którego niektóre powiadomienia nie były wysyłane do użytkowników.


Historia

Zespół postanowił zapisywać wartość null w opcjonalnej właściwości, myśląc, że to poprawne. TypeScript zgłosił błąd, a aby to obejść, musiano rozszerzyć typ do string | null, co wymagało przemyślenia całej logiki biznesowej dotyczącej tych obiektów.