Blog/typescript/TypeScript ilə Supabase İnteqrasiyası — Tam Tip Təhlükəsizliyi
typescript

TypeScript ilə Supabase İnteqrasiyası — Tam Tip Təhlükəsizliyi

B
Baku Stack AI
·19 mart 2026·5 dəq oxuma·23 baxış
typescript.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ BACKEND ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ $ supabase gen types ▓
▓ ✓ database.ts ready ▓
▓ ▓
▓ DB → Types → UI ▓
▓ ░░░░░░░░░░░░░░░░░░░░ ▓
▓ PostgreSQL ▓▓▓▓▓▓░░ ▓
▓ TypeScript ▓▓▓▓▓▓▓▓ ▓
▓ Type Safety ▓▓▓▓▓▓▓▓ ▓
▓ ▓
▓ ● any→0 ● bug→↓40% ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

Supabase + TypeScript ilə runtime xətaları unudun: avtomatik tip generasiyası, end-to-end type safety və real layihə nümunəsi ilə tam praktiki bələdçi.

TypeScript ilə Supabase İnteqrasiyası — Tam Tip Təhlükəsizliyi

Salam, developer dostlar! 👋

Bakıda son 2 ildə startup ekosistemi ciddi böyüyür. Kontakt Home-un e-commerce platformasından tutmuş, Bravo-nun loyalty sistemlərinə qədər — backend-də sürətli, ucuz və scalable həllər lazımdır. Firebase alternativləri arasında Supabase artıq ciddi oyunçudur: açıq mənbəli, PostgreSQL əsaslı, və ən əsası — TypeScript ilə mükəmməl işləyir.

Bu məqalədə sənə Supabase + TypeScript inteqrasiyasının tam yolunu göstərəcəm. Söhbət sadəcə any yazıb keçməkdən deyil — database-dən UI-a qədər tam tip təhlükəsizliyindən gedir.


Niyə Supabase? Niyə TypeScript?

Əvvəlcə rəqəmlərə baxaq:

  • Supabase 2025-ci ildə 900,000+ aktiv layihəyə çatıb (rəsmi blog)
  • TypeScript Stack Overflow 2025 sorğusunda ən çox sevilən dillərin 3-cüsüdür
  • Bakıda TypeScript bilən developer üçün orta maaş 1800-3500 AZN arasıdır (LinkedIn və boss.az datası əsasında), sadəcə JavaScript bilənlərə nisbətən 20-30% yuxarı

Supabase sənə bunları verir:

  • ✅ PostgreSQL database + real-time subscriptions
  • ✅ Authentication (Google, GitHub, email)
  • ✅ Storage (fayl yükləmə)
  • ✅ Edge Functions (serverless)
  • Avtomatik TypeScript tip generasiyası

Son punkt — bu məqalənin əsas mövzusudur.


Addım 1: Layihəni Qururuq

Supabase hesabı açıb yeni layihə yarat. Sonra terminal aç:

bash
npm create vite@latest my-app -- --template react-ts cd my-app npm install @supabase/supabase-js npm install supabase --save-dev

Supabase CLI ilə login ol:

bash
npx supabase login npx supabase init npx supabase link --project-ref YOUR_PROJECT_REF

Addım 2: Database Strukturu

Tutaq ki, Bakıda restoran sifariş sistemi qurursan. SQL ilə table yaradırıq:

sql
CREATE TABLE restaurants ( id UUID DEFAULT gen_random_uuid() PRIMARY KEY, name TEXT NOT NULL, cuisine TEXT NOT NULL, rating NUMERIC(2,1) CHECK (rating >= 0 AND rating <= 5), district TEXT NOT NULL, -- Nəsimi, Yasamal, Səbail... created_at TIMESTAMPTZ DEFAULT now() ); CREATE TABLE orders ( id UUID DEFAULT gen_random_uuid() PRIMARY KEY, restaurant_id UUID REFERENCES restaurants(id), customer_name TEXT NOT NULL, total_azn NUMERIC(10,2) NOT NULL, status TEXT DEFAULT 'pending' CHECK (status IN ('pending','preparing','delivered','cancelled')), created_at TIMESTAMPTZ DEFAULT now() );

Addım 3: Avtomatik Tip Generasiyası ✨

Bax, sehrli hissə budur. Bir əmrlə bütün database strukturun TypeScript tiplərinə çevrilir:

bash
npx supabase gen types typescript --linked > src/types/database.ts

Bu əmr sənin üçün belə bir fayl yaradır:

typescript
// src/types/database.ts (avtomatik generasiya olunub) export type Json = string | number | boolean | null | { [key: string]: Json } | Json[] export interface Database { public: { Tables: { restaurants: { Row: { id: string name: string cuisine: string rating: number | null district: string created_at: string } Insert: { id?: string name: string cuisine: string rating?: number | null district: string created_at?: string } Update: { id?: string name?: string cuisine?: string rating?: number | null district?: string created_at?: string } } orders: { Row: { id: string restaurant_id: string | null customer_name: string total_azn: number status: string | null created_at: string } Insert: { id?: string restaurant_id?: string | null customer_name: string total_azn: number status?: string | null created_at?: string } Update: { id?: string restaurant_id?: string | null customer_name?: string total_azn?: number status?: string | null created_at?: string } } } } }

Diqqət et: Row, InsertUpdate ayrı-ayrı tipdirlər. Insert-də id optional-dır (database özü yaradır), Update-də isə hər şey optional-dır (yalnız dəyişən sahələri göndərirsən).


Addım 4: Typed Supabase Client

İndi client-i tiplə birlikdə yaradırıq:

typescript
// src/lib/supabase.ts import { createClient } from '@supabase/supabase-js' import type { Database } from '../types/database' const supabaseUrl = import.meta.env.VITE_SUPABASE_URL const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY export const supabase = createClient<Database>(supabaseUrl, supabaseKey)

Bu bir sətirlik <Database> generic — hər şeyi dəyişir. Artıq bütün query-lərin tiplidir.


Addım 5: CRUD Əməliyyatları — Tam Type Safety

typescript
// src/services/restaurant.ts import { supabase } from '../lib/supabase' import type { Database } from '../types/database' type Restaurant = Database['public']['Tables']['restaurants']['Row'] type NewRestaurant = Database['public']['Tables']['restaurants']['Insert'] // ✅ SELECT — nəticə avtomatik Restaurant[] tipindədir export async function getRestaurants(district?: string) { let query = supabase .from('restaurants') // ← autocomplete işləyir! .select('*') if (district) { query = query.eq('district', district) } const { data, error } = await query // data tipi: Restaurant[] | null if (error) throw error return data } // ✅ INSERT — yanlış sahə göndərsən, COMPILE vaxtı xəta verir export async function addRestaurant(restaurant: NewRestaurant) { const { data, error } = await supabase .from('restaurants') .insert(restaurant) .select() .single() if (error) throw error return data // tipi: Restaurant } // ✅ UPDATE — yalnız mövcud sahələri qəbul edir export async function updateRating(id: string, rating: number) { const { data, error } = await supabase .from('restaurants') .update({ rating }) // ← yalnız Restaurant['Update'] sahələri .eq('id', id) .select() .single() if (error) throw error return data } // ❌ BU COMPILE OLMAYACAQ: // supabase.from('restaurants').insert({ name: 'Test', price: 100 }) // Error: 'price' does not exist in type InsertRestaurant

Gördün? price deyə sahə yoxdur — TypeScript bunu runtime-dan əvvəl tutur. Production-da 3 gecə saat 3-də crash olmaqdansa, VSCode-da qırmızı xətt görmək daha yaxşıdır 😄


Addım 6: React Komponentdə İstifadə

typescript
// src/components/RestaurantList.tsx import { useEffect, useState } from 'react' import { getRestaurants } from '../services/restaurant' import type { Database } from '../types/database' type Restaurant = Database['public']['Tables']['restaurants']['Row'] export function RestaurantList() { const [restaurants, setRestaurants] = useState<Restaurant[]>([]) const [loading, setLoading] = useState(true) useEffect(() => { getRestaurants('Nəsimi') .then(setRestaurants) .catch(console.error) .finally(() => setLoading(false)) }, []) if (loading) return <p>Yüklənir...</p> return ( <ul> {restaurants.map((r) => ( <li key={r.id}> {r.name}{r.cuisine} — ⭐ {r.rating ?? 'N/A'} {/* r.price yazsaq → compile error! */} </li> ))} </ul> ) }

Pro Tip: CI/CD-yə Daxil Et

Database schema dəyişəndə tipləri yeniləməyi unutmamaq üçün bunu package.json-a əlavə et:

json
{ "scripts": { "types:generate": "supabase gen types typescript --linked > src/types/database.ts", "build": "npm run types:generate && tsc && vite build" } }

Beləcə hər build-dən əvvəl tiplər yenilənir. Schema ilə kod heç vaxt sync-dən çıxmır.


Nəticə: Bu Niyə Vacibdir?

Bakıda işləyən bir çox startupda belə bir mənzərə görürəm: backend developer table-a yeni column əlavə edir, frontend developer xəbəri olmur, production-da undefined xətası çıxır, QA tapır, hotfix gedir... Bu dövranı tiplərlə qırmaq olar.

Supabase + TypeScript combo-su sənə bunları verir:

  • 🔒 Database-dən UI-a qədər tam tip təhlükəsizliyi
  • 🚀 Autocomplete — API docs-a baxmağa ehtiyac qalmır
  • 🐛 Bug-ların 40%-i compile vaxtı tutulur (Microsoft-un TypeScript statistikası)
  • 💰 Free tier — Supabase-in pulsuz planı 500MB database, 50,000 aktiv istifadəçi

Əgər Bakıda freelance işləyirsənsə, bir Supabase + Next.js + TypeScript stack ilə saytlar qurub layihə başına 800-2000 AZN qazana bilərsən. Stack sadədir, amma peşəkar görünür.

Tiplərinizi generasiya edin, any-dən uzaq durun, və production-da gecə rahat yatın. 🚀


Sualın var? Kommentdə yaz, ya da Telegram qrupumuza qoşul.

Oxşar məqalələr

typescript.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ TYPESCRIPT ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ z.string() ✓ safe ▓
▓ z.number() ✓ safe ▓
▓ z.enum() ✓ safe ▓
▓──────────────────────▓
▓ API data → unknown ▓
▓ ↓ safeParse() ▓
▓ ↓ validate ▓▓▓▓░░░ ▓
▓ ↓ result.success ▓
▓ ✓ typed & safe! ▓
▓ ● runtime: 100% ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

Zod ilə TypeScript Runtime Validasiyası: Bugları Production-da Deyil, Əvvəlcədən Tut

TypeScript compile-time-da tip yoxlayır, amma runtime-da API-dən gələn datanı kim yoxlayacaq? Zod ilə validasiyanı necə həll edəcəyini real nümunələrlə göstərirəm.

typescript.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ TYPESCRIPT ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ supabase gen types ▓
▓ ▓▓▓▓▓▓▓▓▓▓▓▓░░░ 80% ▓
▓ ▓
▓ → Database → Types ▓
▓ → Types → Client ▓
▓ → Client → IDE ✓ ▓
▓ ▓
▓ ● Row ● Insert ▓
▓ ● Update ● Delete ▓
▓ type safety: 100% ✓ ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

TypeScript ilə Supabase inteqrasiyası — tam tip təhlükəsizliyi

Supabase + TypeScript birlikdə işlədəndə runtime xətaları minimuma enir. Database-dən gələn hər sətir tipli olur. Necə? Bu məqalədə.

typescript.ascii
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ ■ ■ ■ TYPESCRIPT ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓ function id<T>(x:T):T ▓
▓ return x; ▓
▓ ▓
▓ ● id<string>("Bakı") ▓
▓ → "Bakı" ✓ ▓
▓ ● id<number>(2026) ▓
▓ → 2026 ✓ ▓
▓ ▓
▓ Generics skill: ▓
▓ ▓▓▓▓▓▓▓▓░░ 80% ▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓

TypeScript Generics — Nədir, Niyə Lazımdır, Necə İstifadə Olunur?

TypeScript generics-i başa düşmək Bakıda frontend və backend vakansiyaların 70%-ində tələb olunan skilldir. Bu bələdçi ilə generics-i bir dəfəlik öyrən.

← Bloqa qayıt