September 28, 2026

Dasar TypeScript.

Fondasi TypeScript: tipe primitif, array & tuple, interface vs type, union & intersection, literal type, dan type narrowing — dengan contoh yang bisa langsung dijalankan.

TypeScript adalah JavaScript + sistem tipe statis. Semua kode JavaScript yang valid adalah TypeScript yang valid, tapi TypeScript menambahkan anotasi tipe yang dicek saat compile — bukan saat runtime. Hasil akhirnya tetap JavaScript biasa; tipe dihapus total ketika kode dijalankan.

Keuntungannya praktis: autocomplete yang akurat, refactor yang aman, dan bug seperti undefined is not a function tertangkap sebelum sampai ke user.


1. Menjalankan TypeScript

Cara tercepat mencoba tanpa setup proyek:

mkdir belajar-ts && cd belajar-ts
npm init -y
npm install -D typescript
npx tsc --init          # membuat tsconfig.json

Buat index.ts, lalu:

npx tsc --noEmit        # hanya cek tipe, tidak menghasilkan .js
node index.ts           # Node.js 22.18+ / 23.6+ bisa menjalankan .ts langsung (type stripping)

Node.js versi baru menjalankan file .ts dengan cara membuang anotasi tipe saja — ia tidak mengecek tipe. Pengecekan tetap tugas tsc. Jadi alurnya: tsc --noEmit untuk validasi, runtime untuk eksekusi.


2. Tipe Dasar

let nama: string = "Fanny";
let umur: number = 27;
let aktif: boolean = true;
let kosong: null = null;
let belumAda: undefined = undefined;

// Type inference: anotasi sering tidak perlu
let kota = "Semarang"; // otomatis string
// kota = 10;          // ❌ Type 'number' is not assignable to type 'string'
TipeContohCatatan
string, number, boolean"a", 42, truePakai huruf kecil, bukan String/Number
T[] / Array<T>string[]Array dengan elemen sejenis
Tuple[string, number]Panjang & urutan tetap
any—Mematikan pengecekan, hindari
unknown—Versi aman dari any: wajib dicek dulu sebelum dipakai
never—Nilai yang tidak mungkin ada (mis. fungsi yang selalu throw)
void—Fungsi tanpa nilai kembalian
const tags: string[] = ["ts", "js"];
const koordinat: [number, number] = [-6.99, 110.42];

function gagal(pesan: string): never {
  throw new Error(pesan);
}

function log(pesan: string): void {
  console.log(pesan);
}

Fungsi

function tambah(a: number, b: number): number {
  return a + b;
}

// Parameter opsional & default
function sapa(nama: string, salam = "Halo", titik?: string) {
  return `${salam}, ${nama}${titik ?? "!"}`;
}

// Tipe fungsi sebagai nilai
const kali: (a: number, b: number) => number = (a, b) => a * b;

Sintaks arrow function tetap sama; TypeScript hanya menambah anotasi pada parameter dan nilai kembalian.


3. Object: interface vs type

Dua cara mendeskripsikan bentuk objek:

interface User {
  id: number;
  nama: string;
  email?: string;          // opsional
  readonly createdAt: Date; // tidak bisa diubah setelah dibuat
}

type Produk = {
  id: number;
  nama: string;
  harga: number;
};

const u: User = { id: 1, nama: "Fanny", createdAt: new Date() };
// u.createdAt = new Date(); // ❌ read-only

Perbedaannya:

Aspekinterfacetype
Bentuk objek✅✅
Union / primitif / tuple❌✅ (type Id = string | number)
Extendinterface B extends A {}type B = A & { ... }
Declaration merging✅ (deklarasi dua kali digabung)❌ (error duplikat)
Pesan errorBiasanya menampilkan nama interfaceKadang diekspansi
interface Admin extends User {
  role: "admin";
}

type AdminT = User & { role: "admin" };

Aturan praktis: pakai interface untuk bentuk objek publik (props, model data) dan type untuk union, alias, dan komposisi. Yang penting konsisten dalam satu proyek.


4. Union & Intersection

Union (A | B) artinya “salah satu dari”:

type Id = string | number;

function cetakId(id: Id) {
  console.log(`ID: ${id}`);
}

cetakId(10);
cetakId("abc-123");

Literal type membuat union sangat berguna — nilainya dibatasi ke string tertentu:

type Status = "draft" | "published" | "archived";

function ubahStatus(s: Status) { /* ... */ }
ubahStatus("published"); // ✅
// ubahStatus("deleted"); // ❌ tidak ada di union

Intersection (A & B) artinya “gabungan semua properti”:

type Timestamps = { createdAt: Date; updatedAt: Date };
type Artikel = { judul: string; isi: string } & Timestamps;

const a: Artikel = {
  judul: "Belajar TS",
  isi: "...",
  createdAt: new Date(),
  updatedAt: new Date(),
};

5. Type Narrowing

Saat nilai bertipe union, TypeScript memaksa kita mempersempit tipenya sebelum memakai method khusus. Narrowing terjadi otomatis dari pengecekan runtime biasa.

typeof, truthiness, in, instanceof

function format(nilai: string | number | null) {
  if (nilai === null) return "-";              // equality narrowing
  if (typeof nilai === "string") {
    return nilai.toUpperCase();                // di sini: string
  }
  return nilai.toFixed(2);                     // di sini: number
}

type Kucing = { meong(): void };
type Anjing = { gonggong(): void };

function suara(hewan: Kucing | Anjing) {
  if ("meong" in hewan) hewan.meong();         // in narrowing
  else hewan.gonggong();
}

function pesanError(e: unknown) {
  if (e instanceof Error) return e.message;    // instanceof narrowing
  return String(e);
}

Discriminated union

Pola paling berguna di TypeScript: setiap anggota union punya properti “penanda” (biasanya type atau kind).

type Hasil =
  | { status: "loading" }
  | { status: "sukses"; data: string[] }
  | { status: "error"; pesan: string };

function render(h: Hasil): string {
  switch (h.status) {
    case "loading":
      return "Memuat...";
    case "sukses":
      return h.data.join(", ");   // data hanya ada di sini
    case "error":
      return `Gagal: ${h.pesan}`;
    default: {
      const _cek: never = h;      // exhaustiveness check
      return _cek;
    }
  }
}

Jika nanti ada status baru (mis. "kosong") dan lupa ditangani, baris const _cek: never = h langsung error. Ini jaring pengaman yang sangat berharga saat refactor.

Custom type guard

interface Produk { id: number; harga: number }

function isProduk(x: unknown): x is Produk {
  return (
    typeof x === "object" && x !== null &&
    "id" in x && "harga" in x
  );
}

const data: unknown = JSON.parse('{"id":1,"harga":5000}');
if (isProduk(data)) {
  console.log(data.harga * 2); // data: Produk
}

6. as, satisfies, dan Non-null !

// Type assertion: "percayalah, saya tahu tipenya" — tidak ada pengecekan runtime
const input = document.querySelector("#email") as HTMLInputElement;

// satisfies: cek kecocokan TANPA melebarkan tipe
const warna = {
  primer: "#b45309",
  sekunder: [180, 83, 9],
} satisfies Record<string, string | number[]>;

warna.primer.toUpperCase();   // ✅ tetap dikenal sebagai string
warna.sekunder.map((n) => n); // ✅ tetap number[]

// Non-null assertion: buang null/undefined (hati-hati)
const el = document.getElementById("app")!;
OperatorKapan dipakai
as TData dari DOM/API yang tipenya kita tahu pasti
satisfies TObjek konfigurasi: ingin divalidasi tapi tetap tipe spesifik
!Hanya jika benar-benar yakin tidak null

Kesalahan Umum

  1. Memakai any supaya error hilang. any menular: semua yang menyentuhnya ikut kehilangan tipe. Gunakan unknown lalu narrowing.
  2. Mengira tipe ada di runtime. interface tidak bisa dicek dengan instanceof; data dari API tetap perlu divalidasi (type guard atau library seperti Zod).
  3. as untuk “memaksa” tipe yang salah. {} as User lolos compile tapi akan crash saat properti diakses. Assertion bukan konversi.
  4. Terlalu banyak anotasi. const x: number = 5 berlebihan — biarkan inference bekerja, anotasi cukup di parameter fungsi dan batas modul.
  5. Pakai String/Number/Object (huruf besar). Itu tipe wrapper object, bukan primitif.
  6. Lupa exhaustiveness check pada discriminated union, sehingga case baru terlewat diam-diam.
  7. Menyalahgunakan !. Non-null assertion hanya memindahkan error dari compile-time ke runtime.

Ringkasan

  • TypeScript = JavaScript + tipe yang dicek saat compile, lalu dihapus.
  • interface untuk bentuk objek, type untuk union dan komposisi.
  • Union + literal type + discriminated union adalah kombinasi paling produktif.
  • Narrowing terjadi lewat typeof, in, instanceof, equality, dan type guard.
  • Lanjut ke Generics & Utility Types untuk membuat tipe yang reusable.

Hey! I’m Fanny, the software engineer tending to this digital garden. You can read more about me, or subscribe by email.

Comments