---
title: Adnotacje typów
description: Dodawaj typy dokładnie tam, gdzie SQL ich potrzebuje. Adnotacje sprawdzają założenia i nigdy nie zmieniają wyników.
species: concept
---

# Adnotacje typów

Typesql jest SQL z opcjonalnymi typami. Oznaczasz miejsca zależne od założenia — ta kolumna nigdy nie jest null, ta liczba mieści się w `decimal(28,2)`, ten JSON ma pole `plan` — a moduł sprawdzający weryfikuje je względem rzeczywistego schematu jeziora przed wykonaniem zapytania i po każdej zmianie schematu.

```typesql check=p1
select
  id,
  amount satisfies integer!,
  metadata::json<{plan: string}> ->> 'plan' as plan
from titan.stripe.charges
```

## Gwarancja

Adnotacje nigdy nie zmieniają wyniku zapytania. Usuń wszystkie adnotacje z dokumentu typesql, a otrzymasz zwykły SQL działający identycznie — te same wiersze, wartości i wszystko inne. To gwarancja strukturalna, a nie konwencja: typy są sprawdzane i wymazywane; żadna ścieżka wykonania nie może ich nawet odczytać.

Nie musisz więc podejmować decyzji o migracji. Oznacz jedno wyrażenie w jednym zapytaniu i na tym zakończ albo nadaj typy całemu modelowi — każdy punkt między „zwykłym SQL” a „pełnymi typami” jest działającym programem.

## `satisfies`: sprawdzanie wyrażenia

Zapisz `expr satisfies type` wszędzie tam, gdzie dozwolone jest wyrażenie:

```typesql check=p1
select
  round(sum(amount) / 100.0, 2) satisfies decimal(38,2) as gross_volume
from titan.stripe.charges
where not _deleted
```

Jeśli zmiana schematu kiedykolwiek sprawi, że wyrażenie przestanie być liczbą dziesiętną, model nie przejdzie kontroli z diagnostyką wskazującą dokładny zakres — zamiast po cichu pokazać śmieci na dashboardzie. Każdy komunikat zawiera stabilny kod `TS`, lokalizację i wiersz `help:` z poprawką.

`satisfies` nie jest rzutowaniem. `amount::string` konwertuje wartość; `amount satisfies string` stwierdza fakt i nie przechodzi kontroli, gdy jest fałszywy. Używaj `::`, aby zmieniać dane, i `satisfies`, aby wykrywać zmiany.

## Brak wartości null: `!` i zawężanie

`string!` oznacza „tekst, który nigdy nie jest null”. Moduł sprawdzający rozumie wpływ logiki zapytania na możliwość wartości null — to przejdzie kontrolę:

```typesql check=p1
select email satisfies string!
from titan.stripe.customers
where email is not null
```

Usuń `where`, a kontrola się nie powiedzie: `email` może być null w schemacie, a zapytanie niczego takiego nie wykluczyło. Działa też odwrotna sytuacja — kolumna bez null staje się opcjonalna po zewnętrznej stronie `left join`, co również jest śledzone. Kontrola odzwierciedla działanie zapytania, nie tylko deklarację schematu.

## Nagłówki CTE z typami

Nagłówek CTE może zadeklarować typy kolumn, zmieniając granicę między etapami zapytania w sprawdzany kontrakt:

```typesql check=p1
with monthly(month: date!, gross_volume: decimal(38,2)) as (
  select
    date_trunc('month', created_at)::date,
    round(sum(amount) / 100.0, 2)
  from titan.stripe.charges
  where not _deleted
  group by 1
)
select * from monthly where gross_volume > 250000
```

Ciało jest sprawdzane względem nagłówka, a wszystko poniżej `monthly` otrzymuje zadeklarowane typy. Po wymazaniu nagłówek traci typy — `with monthly(month, gross_volume) as (…)` — i działa jak zwykły SQL.

## JSON z typami

Nadaj kolumnie JSON strukturę, aby odwołania do niej przestały być domysłami:

```typesql check=p1
select
  metadata::json<{plan: string, seats: integer}> as meta,
  meta ->> 'plan' as plan
from titan.stripe.charges
```

Literówka taka jak `meta ->> 'paln'` staje się błędem kontroli, a nie kolumną null odkrytą trzy dashboardy później.

## W edytorze

Edytor zapytań uruchamia ten sam moduł w trakcie pisania. Wskaż wyrażenie, aby zobaczyć wywnioskowany typ. Podpowiedzi w kodzie pokazują typy już znane modułowi, a kliknięcie jednej zapisuje ją w zapytaniu jako prawdziwą adnotację `satisfies` — stopniowe typowanie jednym kliknięciem. Szybkie poprawki zawierają te same zmiany co sugestie diagnostyki.

## Co dalej

- [Pisanie modeli](/docs/models/authoring) — modele są sprawdzane względem jeziora przy każdym uruchomieniu, a nagłówek `-- lint:` ustala, która diagnostyka blokuje.
- Strony systemu typów opisują pełną gramatykę: typy skalarne, `decimal(p,s)`, listy i struktury, typy tabel oraz sposób typowania kolumn systemowych, takich jak `_synced_at`.
