JavaScript adalah bahasa yang fleksibel, tetapi fleksibilitas itu sering menjadi bumerang: variabel bisa berubah tipe seenaknya, properti yang tidak ada baru ketahuan saat aplikasi sudah berjalan, dan bug muncul di produksi. Di sinilah TypeScript masuk. TypeScript adalah superset dari JavaScript yang menambahkan tipe statis, sehingga banyak kesalahan bisa ditangkap sejak kamu menulis kode — bukan saat runtime. Jika kamu sudah paham dasar-dasar JavaScript: variabel, fungsi, dan DOM, artikel ini akan membawamu naik level dengan TypeScript secara bertahap dan praktis, lengkap dengan contoh kode yang bisa langsung kamu jalankan.
Apa Itu TypeScript dan Kenapa Kamu Butuh?
TypeScript dikembangkan oleh Microsoft dan kini menjadi standar de facto untuk proyek JavaScript berskala besar — dipakai di belakang layar oleh framework seperti Angular, Deno, dan berbagai tool modern. Kode TypeScript dikompilasi menjadi JavaScript biasa, sehingga bisa berjalan di browser maupun Node.js mana pun. Manfaat utamanya adalah type safety: editor (VS Code dan sejenisnya) langsung menandai kesalahan tipe, memberi autocomplete yang jauh lebih akurat, dan membuat refactoring lebih aman karena kompiler memvalidasi setiap perubahan.
Penting dipahami: TypeScript adalah superset JavaScript. Semua kode JavaScript yang valid adalah kode TypeScript yang valid. Kamu tidak perlu menulis ulang proyek dari nol — cukup ubah ekstensi file dari .js menjadi .ts secara bertahap, dan TypeScript akan mulai bekerja.
Prasyarat & Instalasi
Untuk mengikuti tutorial ini, kamu hanya butuh Node.js dan npm (keduanya terpasang bersama). Jalankan perintah berikut di terminal untuk memeriksa versi dan memasang kompiler TypeScript:
# Cek versi Node.js dan npm
node --version
npm --version
# Install TypeScript secara global (sekali saja)
npm install -g typescript
# Atau install lokal di dalam proyek (lebih disarankan)
mkdir belajar-typescript && cd belajar-typescript
npm init -y
npm install --save-dev typescript
# Cek versi compiler
npx tsc --version
Menyiapkan File Konfigurasi tsconfig.json
tsconfig.json adalah pusat kendali kompiler TypeScript. Di dalamnya kita menentukan seberapa ketat pemeriksaan tipe, target JavaScript yang dihasilkan, serta folder input dan output. Buat file berikut di root proyek:
{
"compilerOptions": {
"target": "ES2022",
"module": "commonjs",
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"noImplicitAny": true,
"esModuleInterop": true
},
"include": ["src"]
}
Pastikan opsi strict bernilai true. Mode strict menyalakan seluruh pemeriksaan tipe paling ketat sekaligus — inilah alasan utama kamu memakai TypeScript. Tanpa itu, sebagian besar manfaat type safety tidak akan aktif.
Tipe Dasar: String, Number, Boolean, dan Array
Konsep paling fundamental adalah memberi tahu TypeScript tipe dari setiap variabel dan fungsi. Tipe ditulis setelah nama variabel dengan tanda titik dua (:). Buat file src/index.ts dan coba kode berikut:
// Tipe dasar yang paling sering dipakai
let nama: string = "Budi";
let umur: number = 25;
let aktif: boolean = true;
let nilai: number[] = [80, 90, 75];
let daftarNama: Array<string> = ["Andi", "Sari"];
// Tanpa tipe tertulis, TypeScript menyimpulkannya (type inference)
let kota = "Bandung"; // otomatis bertipe string
// kota = 123; // Error: number tidak bisa masuk ke string
// Tipe fungsi: parameter dan nilai kembalian
function jumlahkan(a: number, b: number): number {
return a + b;
}
console.log(jumlahkan(2, 3)); // 5
Tuple, Enum, dan Tipe Khusus: any, unknown, null
Selain tipe primitif, TypeScript menyediakan beberapa struktur yang sering kamu temui di kode produksi:
// Tuple: array dengan jumlah & tipe elemen yang tetap
let titik: [number, number] = [10, 20];
// Enum: kumpulan konstanta bernama yang lebih mudah dibaca
enum Status {
Draft,
Published,
Archived,
}
let statusArtikel: Status = Status.Published;
// any: mematikan pemeriksaan tipe (gunakan secukupnya)
let bebas: any = 4;
bebas = "sekarang jadi string";
// unknown: seperti any tapi lebih aman, wajib dicek dulu
let tidakDiketahui: unknown = "halo";
if (typeof tidakDiketahui === "string") {
console.log(tidakDiketahui.toUpperCase());
}
// null dan undefined
let kosong: null = null;
let belumDiisi: undefined = undefined;
Hindari penggunaan any secara berlebihan. any mematikan pemeriksaan tipe dan membuat TypeScript kehilangan manfaat utamanya. Jika kamu belum yakin tipenya, gunakan unknown lalu lakukan type narrowing (dibahas di bawah).
Interface & Type Alias: Mendefinisikan Bentuk Objek
Di JavaScript, objek adalah raja. interface dan type alias memungkinkan kita mendeskripsikan bentuk sebuah objek sehingga TypeScript bisa memvalidasi propertinya. Keduanya sering dipakai bergantian, meski ada perbedaan kecil yang tidak akan kita bahas terlalu dalam di sini.
// Interface: mendefinisikan bentuk (shape) sebuah objek
interface Pengguna {
id: number;
nama: string;
email: string;
aktif?: boolean; // properti opsional (tanda tanya)
}
const pengguna: Pengguna = {
id: 1,
nama: "Budi",
email: "budi@example.com",
};
// Type alias: alternatif yang mendukung lebih banyak bentuk tipe
type ID = number | string;
// Interface bisa diwariskan (extends)
interface Admin extends Pengguna {
role: "admin" | "superadmin";
}
Union, Literal, dan Intersection Types
Tiga fitur ini membuat sistem tipe TypeScript jauh lebih ekspresif daripada sekadar "ini number, itu string":
// Union type: nilai boleh salah satu dari beberapa tipe
function formatId(id: number | string): string {
return `ID-${id}`;
}
// Literal type: nilai dibatasi ke nilai tertentu
type Arah = "atas" | "bawah" | "kiri" | "kanan";
function geser(arah: Arah): void {
// hanya 4 nilai di atas yang valid
}
// Intersection type: gabungkan beberapa tipe menjadi satu
type Bernama = { nama: string };
type Bertanggal = { dibuatPada: Date };
type Artikel = Bernama & Bertanggal;
Generics: Fungsi dan Tipe yang Dapat Digunakan Ulang
Generics adalah cara menulis fungsi atau tipe yang bekerja untuk banyak tipe sekaligus, tanpa kehilangan informasi tipe dan tanpa jatuh ke any. Ini adalah salah satu fitur TypeScript yang paling kuat.
// Generics: tulis fungsi sekali, pakai untuk banyak tipe
function identitas<T>(nilai: T): T {
return nilai;
}
const angka = identitas<number>(42);
const teks = identitas<string>("halo");
// Generics pada interface
interface Respons<T> {
status: number;
data: T;
}
const responPengguna: Respons<Pengguna> = {
status: 200,
data: { id: 1, nama: "Budi", email: "budi@example.com" },
};
// Constraint: batasi generic hanya untuk tipe tertentu
function ambilPanjang<T extends { length: number }>(item: T): number {
return item.length;
}
Utility Types: Partial, Pick, Omit, dan Record
TypeScript menyediakan utility types bawaan yang sangat membantu saat mengolah tipe — terutama untuk operasi CRUD (create, read, update, delete) pada data.
interface Produk {
id: number;
nama: string;
harga: number;
deskripsi: string;
}
// Partial: semua properti jadi opsional
type ProdukDraft = Partial<Produk>;
// Pick: ambil hanya properti tertentu
type RingkasanProduk = Pick<Produk, "id" | "nama" | "harga">;
// Omit: buang properti tertentu
type ProdukTanpaDeskripsi = Omit<Produk, "deskripsi">;
// Record: pasangan kunci-nilai dengan tipe seragam
type StokPerGudang = Record<string, number>;
// Readonly: properti tidak bisa diubah setelah dibuat
type ProdukBeku = Readonly<Produk>;
Type Narrowing: Menyempitkan Tipe dengan Type Guards
Saat bekerja dengan union type, TypeScript tidak selalu tahu tipe pastinya. Type narrowing adalah teknik mempersempit tipe melalui pemeriksaan (type guard) sehingga kompiler yakin dengan tipe yang sedang ditangani.
// Narrowing dengan typeof
function cetakNilai(input: string | number) {
if (typeof input === "string") {
console.log(input.toUpperCase()); // pasti string
} else {
console.log(input.toFixed(2)); // pasti number
}
}
// Discriminated union: gunakan properti pembeda (jenis)
type Lingkaran = { jenis: "lingkaran"; jariJari: number };
type Persegi = { jenis: "persegi"; sisi: number };
type Bentuk = Lingkaran | Persegi;
function hitungLuas(bentuk: Bentuk): number {
switch (bentuk.jenis) {
case "lingkaran":
return Math.PI * bentuk.jariJari ** 2;
case "persegi":
return bentuk.sisi * bentuk.sisi;
}
}
Kompilasi: Mengubah .ts Menjadi .js
Browser dan Node.js tidak menjalankan TypeScript secara langsung. Jalankan kompiler untuk mengubah file .ts di folder src menjadi JavaScript di folder dist (sesuai tsconfig.json), lalu jalankan hasilnya:
# Kompilasi semua file .ts sesuai tsconfig.json
npx tsc
# Jalankan hasil kompilasi
node dist/index.js
# Mode watch: otomatis recompile saat file berubah
npx tsc --watch
Studi Kasus: Membangun Klien API Bertipe
Mari gabungkan semuanya. Kita akan membangun klien sederhana yang mengambil data dari sebuah REST API. Berkat tipe, editor akan menandai kesalahan sejak dini — misalnya jika kamu mengetik properti yang tidak ada pada respons.
// Studi kasus: klien API yang aman terhadap tipe
interface Artikel {
id: number;
judul: string;
kategori: string;
}
interface ResponsAPI<T> {
data: T;
status: number;
}
async function ambilArtikel(): Promise<ResponsAPI<Artikel[]>> {
const response = await fetch("https://api.example.com/artikel");
if (!response.ok) {
throw new Error(`Gagal mengambil data: ${response.status}`);
}
return response.json();
}
async function main() {
const { data: artikelList } = await ambilArtikel();
// TypeScript tahu setiap item punya judul & kategori
artikelList.forEach((artikel) => {
console.log(`${artikel.judul} (${artikel.kategori})`);
});
}
main();
Kesimpulan & Langkah Selanjutnya
Selamat! Kamu sudah memahami fondasi TypeScript: tipe dasar, interface, generics, utility types, dan type narrowing. Dengan bekal ini, kamu bisa mulai menambahkan tipe pada proyek JavaScript-mu dan menikmati autocomplete serta deteksi bug yang jauh lebih baik. Untuk melihat TypeScript dipakai di proyek nyata, lanjutkan dengan tutorial kami tentang membangun plugin tool AI dengan TypeScript. Selamat berkoding!
Apakah saya harus belajar JavaScript dulu sebelum TypeScript?
Ya, sangat disarankan. TypeScript adalah superset JavaScript, jadi pemahaman tentang variabel, fungsi, array, objek, dan DOM akan membuat konsep tipe statis jauh lebih mudah dipahami. Kamu bisa memulai dari artikel dasar JavaScript kami.
Apakah TypeScript menggantikan JavaScript?
Tidak. TypeScript dikompilasi menjadi JavaScript biasa sebelum dijalankan. JavaScript tetap menjadi bahasa yang berjalan di browser dan Node.js, sedangkan TypeScript adalah lapisan pengembangan di atasnya yang menambahkan tipe statis.
Bagaimana cara memigrasikan proyek JavaScript ke TypeScript secara bertahap?
Mulailah dengan menambahkan tsconfig.json dengan opsi allowJs dan strict yang awalnya false. Lalu ubah ekstensi file satu per satu dari .js ke .ts, perbaiki error tipe yang muncul, dan tingkatkan keketatan mode strict secara bertahap. Ini jauh lebih aman daripada menulis ulang sekaligus.