TypeScript strict — dlaczego i jak

Frontend ZEUS to Next.js 15 + TypeScript. TypeScript ma sens tylko wtedy, gdy działa w trybie strict — inaczej dostajesz iluzję bezpieczeństwa. Ta lekcja pokazuje, dlaczego strict jest u nas obowiązkowy i jak z nim pracować.

Czym jest strict

strict: true w tsconfig.json włącza zestaw rygorystycznych kontroli naraz — m.in. strictNullChecks, noImplicitAny, strictFunctionTypes. Bez tego null i undefined przechodzą wszędzie, a any mnoży się po cichu.

{
  "compilerOptions": {
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "skipLibCheck": true
  }
}

Standard ProfessNet: każdy projekt frontu ma strict: true plus noUncheckedIndexedAccess. To ostatnie wymusza obsługę przypadku, gdy indeks tablicy zwraca undefined.

null i undefined są jawne

W strict string nie może być null. Jeśli wartość bywa pusta, typ to mówi.

// typ jawnie dopuszcza brak wartości
function findProbe(id: string): Probe | undefined {
  return probes.find((p) => p.id === id);
}

const probe = findProbe(id);
probe.host;                    // błąd — probe może być undefined
if (probe) {
  probe.host;                  // OK — zawężenie typu
}

Walka z any

any wyłącza TypeScript. Zamiast niego używaj unknown i zawężaj typ jawnie.

// źle — any przepuszcza wszystko
function parse(raw: any) {
  return raw.data.items;       // brak żadnej kontroli
}

// dobrze — unknown wymusza sprawdzenie
function parse(raw: unknown): Item[] {
  const data = ScanResultSchema.parse(raw);   // np. zod
  return data.items;
}

Standard ProfessNet: any jest zabronione w nowym kodzie (reguła ESLint @typescript-eslint/no-explicit-any). Granice z zewnętrznym światem (API, localStorage) walidujemy schematem (zod) i dostajemy bezpieczny typ.

Typy z jednego źródła prawdy

Nie przepisujemy typów ręcznie. Wyprowadzamy je ze schematu albo z backendu.

import { z } from "zod";

export const ProbeSchema = z.object({
  id: z.string(),
  host: z.string(),
  forest: z.string(),
});

export type Probe = z.infer<typeof ProbeSchema>;   // typ = schema
KonstrukcjaZamiast
unknown + walidacjaany
`Xundefined`
z.infer<...>ręcznie pisany interfejs
as constluźny string/number

Sprawdzanie typów w CI

tsc --noEmit            # sam type-check, bez budowania

Komendę odpalamy w CI obok ESLint. Czerwony tsc blokuje merge.

Wskazówka: nie używaj // @ts-ignore. Jeśli musisz, to // @ts-expect-error z komentarzem — zniknie automatycznie, gdy błąd przestanie występować.


Strict to różnica między „kompiluje się" a „działa". Włączony od pierwszego dnia projektu kosztuje niewiele; włączony później to bolesny refaktor. Dlatego w ZEUS-ie jest standardem od startu.