MODUL 1 PAW

praktikum-perpustakaan/
  package.json
  tsconfig.json
  src/
    tipe.ts
    interface.ts
    generik.ts
    uji-generik.ts
    async.ts
    index.ts

Percobaan 1: Memeriksa Lingkungan & Inisialisasi Proyek

Langkah awal dilakukan dengan memeriksa versi runtime Node.js, npm, dan tsc:

node --version
npm --version
npx tsc --version

Buat folder proyek baru:

mkdir praktikum-perpustakaan
cd praktikum-perpustakaan

Konfigurasi file package.json:

{
  "name": "praktikum-perpustakaan",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "build": "tsc",
    "dev": "tsx src/index.ts"
  },
  "devDependencies": {
    "typescript": "5.9.3",
    "tsx": "4.23.12"
  }
}

Jalankan perintah npm install untuk memasang dependensi. Selanjutnya buat konfigurasi TypeScript pada file tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "dist",
    "rootDir": "src",
    "sourceMap": true
  },
  "include": ["src"]
}
---

Percobaan 2: Tipe Data Dasar, Interface, & Union Type

File src/tipe.ts mendefinisikan tipe dasar, union type, dan fungsi konversi status stok:

const judul: string = "Pengantar Pemrograman Web";
const jumlahHalaman: number = 320;
const masihDipakai: boolean = true;

let kodeBuku: string | number;
kodeBuku = "BK-001";
kodeBuku = 42;

export function statusStok(stok: number): string {
  return stok > 0 ? `Tersedia ${stok} eksemplar` : "Stok habis";
}

console.log(`${judul}, ${jumlahHalaman} halaman`);
console.log(`Kode buku: ${kodeBuku}`);
console.log(statusStok(5));

File src/interface.ts mendefinisikan struktur objek domain perpustakaan dengan opsi properti opsional:

export type Kategori = {
  id: number;
  nama: string;
};

export interface Buku {
  id: number;
  judul: string;
  penulis: string;
  isbn: string;
  kategori: Kategori[];
  stok?: number;
}

export interface Anggota {
  id: number;
  nama: string;
  email: string;
  alamat?: string | null;
}

export function deskripsiBuku(buku: Buku): string {
  const namaKategori = buku.kategori.map((k) => k.nama).join(", ");
  const infoStok =
    buku.stok !== undefined ? `${buku.stok} eksemplar` : "stok belum dicatat";
  return `${buku.judul} oleh ${buku.penulis} (${namaKategori}), ${infoStok}`;
}

export const bukuContoh: Buku = {
  id: 1,
  judul: "Pengantar Basis Data",
  penulis: "Andi Pratama",
  isbn: "978-602-0000-001-1",
  kategori: [{ id: 1, nama: "Komputer" }],
  stok: 3,
};

Eksekusi kode percobaan 2:

npx tsx src/interface.ts
---

Percobaan 3: Fungsi Generik

File src/generik.ts menyediakan fungsi pencarian generik:

export interface Buku {
  id: number;
  judul: string;
  penulis: string;
  isbn: string;
  stok?: number;
}

export interface HasilPencarian<T> {
  katakunci: string;
  hasil: T[];
}

export function cariBuku<T>(
  daftar: T[],
  katakunci: string,
  ambilJudul: (item: T) => string
): HasilPencarian<T> {
  const kunci = katakunci.toLowerCase();
  const hasil = daftar.filter((item) =>
    ambilJudul(item).toLowerCase().includes(kunci)
  );
  return { katakunci, hasil };
}

Pengujian fungsi generik pada file src/uji-generik.ts:

import { cariBuku, type Buku } from "./generik.js";

const katalog: Buku[] = [
  { id: 1, judul: "Pengantar Basis Data", penulis: "Andi Pratama", isbn: "978-001", stok: 3 },
  { id: 2, judul: "Jaringan Komputer", penulis: "Siti Rahma", isbn: "978-002", stok: 5 },
];

const hasil = cariBuku(katalog, "basis", (buku) => buku.judul);
console.log(`Kata kunci "${hasil.katakunci}" ditemukan ${hasil.hasil.length} buku.`);

Jalankan pengujian generik:

npx tsx src/uji-generik.ts
---

Percobaan 4: Asynchronous TypeScript & Main Entry Point

File src/async.ts menangani operasi peminjaman berbasis Promise dan async/await:

export interface Peminjaman {
  id: number;
  judulBuku: string;
  namaAnggota: string;
  tanggalKembali: string;
}

export function tunggu(ms: number): Promise<string> {
  return new Promise((resolve) => {
    setTimeout(() => resolve(`selesai setelah ${ms} ms`), ms);
  });
}

export async function catatPeminjaman(
  id: number,
  judulBuku: string
): Promise<Peminjaman> {
  await tunggu(100);
  return {
    id,
    judulBuku,
    namaAnggota: "Rina",
    tanggalKembali: "2026-09-09",
  };
}

Entry point utama seluruh modul pada src/index.ts:

import { statusStok } from "./tipe.js";
import { deskripsiBuku, bukuContoh } from "./interface.js";
import { cariBuku } from "./generik.js";
import { catatPeminjaman } from "./async.js";

async function main(): Promise<void> {
  console.log("=== Proyek TypeScript: Perpustakaan ===");
  console.log(deskripsiBuku(bukuContoh));
  console.log(statusStok(4));

  const hasil = cariBuku([bukuContoh], "basis", (buku) => buku.judul);
  console.log(`Hasil cari "${hasil.katakunci}": ${hasil.hasil.map((b) => b.judul).join(", ")}`);

  const peminjaman = await catatPeminjaman(1, "Pengantar Basis Data");
  console.log(
    `Peminjaman ${peminjaman.id}: ${peminjaman.judulBuku} oleh ${peminjaman.namaAnggota}, kembali ${peminjaman.tanggalKembali}`
  );
}

main();

Jalankan seluruh proyek menggunakan script dev:

npm run dev

Lakukan pemeriksaan ketaatan tipe data tanpa menghasilkan output JavaScript:

npx tsc --noEmit