Asercje a strażnicy typów
W miarę możliwości preferuj sprawdzanie w czasie wykonywania zamiast asercji
Asercje a strażnicy typów to bezpłatna lekcja TypeScript Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej TypeScript Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs TypeScript Academy zawiera 4 lekcji w sumie.
Dwa sposoby przekonania kompilatora
Gdy kompilator nie zna dokładnego typu wartości, mają Państwo dwie możliwości: wykonać asercję (zadeklarować typ) albo użyć strażnika (potwierdzić typ w czasie działania). Wyglądają podobnie, ale zapewniają zupełnie inny poziom bezpieczeństwa.
function viaAssert(v: unknown): number {
return (v as number) + 1; // claim
}
function viaGuard(v: unknown): number {
return typeof v === 'number' ? v + 1 : 0; // prove
}
console.log(viaAssert(5), viaGuard(5), viaGuard('x'));Asercje niczego nie weryfikują
Asercja jest obietnicą bez mechanizmu egzekwowania. Jeśli okaże się błędna, błąd ujawni się dopiero w czasie działania. Asercje zamieniają bezpieczeństwo na wygodę.
const v: unknown = 'hello';
const n = v as number;
console.log(n.toFixed(2)); // runtime error: toFixed is not a functionStrażniki typu weryfikują w czasie działania
Strażnik typu rzeczywiście sprawdza wartość. Jeśli sprawdzenie się powiedzie, zarówno Państwo, jak i kompilator wiedzą, że typ jest poprawny — zawężenie ma za sobą rzeczywisty test w czasie działania.
function toFixed2(v: unknown): string {
if (typeof v === 'number') return v.toFixed(2);
return 'N/A';
}
console.log(toFixed2(3.14159), toFixed2('hi'));Niestandardowe funkcje strażników typu
Złożone sprawdzenia można zamknąć w wielokrotnie używanej funkcji strażnika zwracającej value is T. Cała baza kodu korzysta wtedy z jednej, dobrze przetestowanej walidacji.
type Email = { address: string };
function isEmail(v: unknown): v is Email {
return typeof v === 'object' && v !== null &&
'address' in v && typeof (v as any).address === 'string';
}
console.log(isEmail({ address: 'a@b.com' }), isEmail(null));Strażniki można łączyć i ponownie wykorzystywać
Ponieważ strażniki są zwykłymi funkcjami, można je łączyć, testować i ponownie wykorzystywać. Asercje są natomiast rozproszonymi deklaracjami, których nie da się centralnie zweryfikować.
function isString(v: unknown): v is string { return typeof v === 'string'; }
function isNonEmpty(v: unknown): v is string {
return isString(v) && v.length > 0;
}
console.log(isNonEmpty('hi'), isNonEmpty(''));Funkcje asercji z użyciem asserts
TypeScript oferuje również funkcje asercji. Ich adnotacja typu zwracanego używa słowa kluczowego asserts. Jeśli funkcja zakończy działanie normalnie, kompilator od tego momentu zawęża typ argumentu; jeśli warunek nie zostanie spełniony, funkcja zgłasza wyjątek.
function assertNumber(v: unknown): asserts v is number {
if (typeof v !== 'number') throw new Error('not a number');
}
function use(v: unknown): number {
assertNumber(v); // after this line, v is number
return v * 2;
}
console.log(use(21));asserts a value is
Strażnik value is T zwraca wartość logiczną, na podstawie której można wykonać rozgałęzienie. Funkcja asserts value is T zgłasza wyjątek w razie niepowodzenia i zawęża typ do końca zakresu. Oba rozwiązania opierają się na sprawdzeniu w czasie działania, w przeciwieństwie do zwykłego as.
function assertDefined<T>(v: T): asserts v is NonNullable<T> {
if (v === null || v === undefined) throw new Error('missing');
}
const maybe: string | null = 'ok';
assertDefined(maybe);
console.log(maybe.length); // narrowed to stringGeneryczne funkcje asercji
Funkcje asercji świetnie nadają się do wielokrotnego używania jako warunki wstępne. Pojedyncza funkcja pomocnicza assert(condition) może pilnować niezmienników w całym kodzie i natychmiast zgłaszać wyjątek w razie ich naruszenia.
function assert(cond: unknown, msg: string): asserts cond {
if (!cond) throw new Error(msg);
}
function half(n: number): number {
assert(n % 2 === 0, 'must be even');
return n / 2;
}
console.log(half(8));Porównanie poziomu bezpieczeństwa
Od najbezpieczniejszego do najbardziej ryzykownego rozwiązania: strażniki typu i funkcje asercji (sprawdzane w czasie działania) stoją wyżej niż zwykłe asercje as (niesprawdzane), a te z kolei wyżej niż podwójne asercje (aktywnie wprowadzające w błąd). Należy wybierać najbezpieczniejsze narzędzie odpowiednie do sytuacji.
// Safe: guard
function safe(v: unknown) {
return typeof v === 'string' ? v.trim() : '';
}
console.log(safe(' hi '));Wybór właściwego narzędzia
Ze strażnika typu należy korzystać, gdy wykonywane jest rozgałęzienie na podstawie typu. Funkcji asercji należy używać, gdy warunek wstępny musi być spełniony albo wykonanie powinno zostać przerwane. as należy stosować tylko wtedy, gdy zawężenie jest niemożliwe (np. przy specjalizacji elementów DOM).
function getInput(v: unknown): asserts v is string {
if (typeof v !== 'string') throw new Error('expected string');
}
const raw: unknown = 'name';
getInput(raw);
console.log(raw.toUpperCase());Sprawdzenia w czasie działania są lepsze
Powtarzający się motyw tego kursu brzmi: należy preferować sprawdzenia w czasie działania zamiast asercji. Strażniki i funkcje asercji zapewniają zarówno typy w czasie kompilacji, jak i bezpieczeństwo w czasie działania. Asercje zapewniają tylko deklarację.
function parsePort(v: unknown): number {
if (typeof v === 'number' && Number.isInteger(v)) return v;
throw new Error('invalid port');
}
console.log(parsePort(8080));Szybki test
Sprawdźcie Państwo swoją wiedzę o asercjach i strażnikach typu.
Podsumowanie: asercje a strażniki
Nauczyli się Państwo, że:
- Strażniki typu (
value is T) potwierdzają typ w czasie działania i umożliwiają rozgałęzienia. - Funkcje asercji (
asserts value is T) zgłaszają wyjątek w razie niepowodzenia i zawężają typ w dalszej części kodu. - Zwykłe asercje
astylko deklarują typ — nie zapewniają bezpieczeństwa w czasie działania. - Należy preferować narzędzia sprawdzane w czasie działania, a asercje rezerwować dla przypadków, których nie można obsłużyć za pomocą zawężania.
Następny kurs: opcjonalne łańcuchowanie i koalescencja wartości nullish.
function isPositive(v: unknown): v is number {
return typeof v === 'number' && v > 0;
}
console.log(isPositive(5), isPositive(-1));Często zadawane pytania
Czy lekcja „Asercje a strażnicy typów” jest bezpłatna?
Tak — pełny tekst „Asercje a strażnicy typów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu TypeScript Academy, przejdź na CoddyKit PRO. Kurs TypeScript Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Asercje a strażnicy typów”?
W miarę możliwości preferuj sprawdzanie w czasie wykonywania zamiast asercji Ćwiczysz TypeScript Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć TypeScript Academy?
Nie wymagamy żadnego doświadczenia. TypeScript Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Asercje a strażnicy typów”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji TypeScript Academy?
Tak. Każda lekcja TypeScript Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Słowo kluczowe as do asercji typów
- Operator asercji non-null
- Podwójne asercje i związane z nimi ryzyko
- Asercje a strażnicy typów