Proyek Akhir: Manajer Tugas Bertipe Aman

Menggabungkan semua yang dipelajari — type alias, union literal, interface, class generik, utility types, Result type, dan penanganan error — dalam proyek Manajer Tugas yang aman tipe.

Part 24 dari 24 ± 75 menit Gratis

Selamat sudah sampai di sini! 🎉

Di bab terakhir kita merangkai semuanya menjadi satu program kecil yang rapi: Manajer Tugas. Kamu akan memakai tipe untuk memodelkan data, class untuk menyimpan state, utility types untuk turunan, dan Result type untuk kegagalan yang wajar.

Langkah 1 — Modelkan data lebih dulu

Aturan emas proyek TypeScript: mulai dari tipe. Setelah bentuk data jelas, kode lainnya mengikuti.

type Prioritas = "rendah" | "sedang" | "tinggi"

interface Tugas {
  readonly id: number
  judul: string
  selesai: boolean
  prioritas: Prioritas
  tenggat?: string          // opsional, format "2026-12-31"
}

type TugasBaru = Omit<Tugas, "id" | "selesai">       // data yang diisi pengguna
type PerubahanTugas = Partial<Omit<Tugas, "id">>      // untuk edit: semua opsional, id tak boleh diubah

Langkah 2 — Tentukan bentuk hasil

type Hasil<T> =
  | { ok: true; nilai: T }
  | { ok: false; galat: string }

Langkah 3 — Class yang menyimpan state

class DaftarTugas {
  private tugas: Tugas[] = []
  private idBerikut = 1

  tambah(baru: TugasBaru): Tugas {
    const t: Tugas = { id: this.idBerikut++, selesai: false, ...baru }
    this.tugas.push(t)
    return t
  }

  selesaikan(id: number): Hasil<Tugas> {
    const t = this.tugas.find((x) => x.id === id)
    if (!t) return { ok: false, galat: `Tugas ${id} tidak ditemukan` }
    t.selesai = true
    return { ok: true, nilai: t }
  }

  ubah(id: number, perubahan: PerubahanTugas): Hasil<Tugas> {
    const t = this.tugas.find((x) => x.id === id)
    if (!t) return { ok: false, galat: `Tugas ${id} tidak ditemukan` }
    Object.assign(t, perubahan)
    return { ok: true, nilai: t }
  }

  daftar(filter?: { prioritas?: Prioritas; selesai?: boolean }): Tugas[] {
    return this.tugas.filter(
      (t) =>
        (filter?.prioritas === undefined || t.prioritas === filter.prioritas) &&
        (filter?.selesai === undefined || t.selesai === filter.selesai),
    )
  }

  ringkasan(): Record<Prioritas, number> {
    const hasil: Record<Prioritas, number> = { rendah: 0, sedang: 0, tinggi: 0 }
    for (const t of this.tugas) hasil[t.prioritas]++
    return hasil
  }
}

Mengapa desain ini kuat?

  • readonly id + Omit<..., "id"> pada input: mustahil tak sengaja mengubah atau memalsukan id.
  • Prioritas sebagai literal union: typo "tingi" langsung ditolak.
  • Hasil<Tugas>: pemanggil dipaksa memeriksa ok sebelum memakai nilai.
  • Record<Prioritas, number> pada ringkasan: jika kelak ditambah prioritas "darurat" dan lupa mengisinya, compiler langsung memberi tahu.
  • private tugas: state hanya bisa diubah lewat metode yang menjaga aturan.

Langkah 4 — Memakai

const d = new DaftarTugas()
d.tambah({ judul: "Belajar generics", prioritas: "tinggi" })
d.tambah({ judul: "Cuci piring", prioritas: "rendah" })

const r = d.selesaikan(1)
if (r.ok) console.log("Selesai:", r.nilai.judul)
else console.log(r.galat)

Ide pengembangan setelah kursus

  • Simpan ke localStorage / file JSON, dan validasi saat membaca (bab 22).
  • Tambah pengurutan berdasarkan tenggat; buat tipe Urutan = "tenggat" | "prioritas".
  • Bungkus jadi API dengan Express + Zod, atau antarmuka dengan React/Vue.
  • Tulis tes dengan Vitest/Jest — tipe dan tes saling melengkapi.

Jalan belajar berikutnya

  1. Pelajari framework: React, Vue, Next.js (semua mendukung TS penuh).
  2. Pelajari backend: NestJS atau Express + Prisma.
  3. Dalami TypeScript: Type Challenges di GitHub dan buku Effective TypeScript.

Setelah menyelesaikan latihan ini, kamu siap mengikuti Kuis Akhir (25 soal). Skor yang baik membuka sertifikat penyelesaian course.

Praktikkan langsung, gratis

Tulis dan jalankan kode langsung di browser, dapatkan penilaian otomatis. Daftar gratis kapan saja untuk menyimpan progres dan meraih sertifikat.

Coba latihan sekarang, tanpa daftar
Bagikan: WhatsApp Facebook LinkedIn X