1. Pengenalan TypeScript
TypeScript adalah bahasa pemrograman yang dikembangkan oleh Microsoft dan pertama kali dirilis pada tahun 2012. TypeScript merupakan superset dari JavaScript, artinya semua kode JavaScript valid di TypeScript, tetapi TypeScript menambahkan fitur static typing (pengetikan statis) yang membantu mendeteksi error sebelum kode dijalankan.
TypeScript sangat populer di kalangan pengembang profesional karena membantu membuat kode yang lebih aman, mudah dipelihara, dan scalable. Banyak framework besar seperti Angular, NestJS, dan bahkan React mendukung TypeScript secara resmi.
Mengapa Memilih TypeScript?
| Keunggulan | Penjelasan |
|---|---|
| Static Typing | Menangkap error saat development sebelum kode dijalankan |
| Autocomplete | IDE seperti VS Code memberikan saran kode yang sangat akurat |
| Refactoring Aman | Mengubah nama fungsi/variabel secara otomatis dan aman |
| Dokumentasi Built-in | Tipe data berfungsi sebagai dokumentasi yang selalu akurat |
| Kompatibel JS | Semua kode JavaScript valid di TypeScript |
| Ekosistem Besar | DefinitelyTyped menyediakan tipe untuk ribuan library JavaScript |
TypeScript vs JavaScript
| Aspek | TypeScript | JavaScript |
|---|---|---|
| Typing | Static (diketahui saat compile) | Dynamic (diketahui saat runtime) |
| Compile | Perlu compile ke JavaScript | Tidak perlu compile |
| Error Detection | π’ Saat coding (compile time) | π΄ Saat dijalankan (runtime) |
| IDE Support | π’ Sangat Baik | π‘ Cukup |
| Learning Curve | π‘ Sedang | π’ Mudah |
| Fitur | Interfaces, Generics, Enums, dll | ES6+ standar |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β ALUR KERJA TYPESCRIPT β β β β ββββββββββββββββ ββββββββββββββββ βββββββββββββ β β β TypeScript βββββΆβ tsc βββββΆβ JavaScriptβ β β β (.ts) β β Compiler β β (.js) β β β β + Type Check β β (tsc) β β β β β ββββββββββββββββ ββββββββββββββββ βββββββ¬ββββββ β β β β β βββββββββΌβββββββ β β β Browser / β β β β Node.js β β β β Runtime β β β ββββββββββββββββ β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
2. Instalasi TypeScript
TypeScript memerlukan Node.js untuk diinstal. Berikut panduan langkah demi langkah untuk menginstal TypeScript di berbagai platform.
Prasyarat: Instal Node.js
# 1. Kunjungi https://nodejs.org/ # 2. Download versi LTS (Long Term Support) # 3. Jalankan installer, ikuti wizard # Verifikasi instalasi Node.js: node --version # Output: v20.11.0 npm --version # Output: 10.2.4
Instalasi TypeScript Global
# Instal TypeScript secara global npm install -g typescript # Verifikasi instalasi tsc --version # Output: Version 5.4.5 # Instal TypeScript secara lokal (untuk proyek) mkdir my-project && cd my-project npm init -y npm install typescript --save-dev # Inisialisasi konfigurasi TypeScript npx tsc --init # Membuat file tsconfig.json
Konfigurasi tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Menjalankan TypeScript Pertama
// File: src/hello.ts
function sapa(nama: string): string {
return `Halo, ${nama}! Selamat datang di TypeScript!`;
}
const pesan: string = sapa("BeebaneLabs");
console.log(pesan);
// Kompilasi dan jalankan:
// npx tsc src/hello.ts
// node src/hello.js
// Output: Halo, BeebaneLabs! Selamat datang di TypeScript!
Watch Mode & ts-node
# Watch mode β otomatis compile saat file berubah npx tsc --watch # ts-node β jalankan TypeScript langsung tanpa compile manual npm install -g ts-node ts-node src/hello.ts # Output: Halo, BeebaneLabs! Selamat datang di TypeScript! # Atau gunakan nodemon untuk auto-restart npm install -g nodemon nodemon --exec ts-node src/hello.ts
Gunakan VS Code sebagai editor β VS Code memiliki dukungan TypeScript yang sangat baik secara built-in, termasuk autocomplete, error highlighting, dan refactoring. Tidak perlu install ekstensi tambahan!
3. Type Annotations
Type annotations adalah cara untuk memberitahu TypeScript tipe data dari variabel, parameter, atau return value. Dengan type annotations, TypeScript bisa mendeteksi error sebelum kode dijalankan.
Tipe Data Dasar
| Tipe | Contoh | Penjelasan |
|---|---|---|
string | "hello", 'world' | Teks / string |
number | 42, 3.14, -10 | Semua angka (int & float) |
boolean | true, false | Boolean / logika benar-salah |
null | null | Nilai kosong yang disengaja |
undefined | undefined | Nilai belum didefinisikan |
any | bebas apapun | Tipe apapun (hindari!) |
void | fungsi tanpa return | Tidak mengembalikan nilai |
never | throw error | Tidak pernah selesai |
Deklarasi Variabel dengan Tipe
// Type annotations dasar let nama: string = "Budi Santoso"; let umur: number = 25; let tinggi: number = 175.5; let isMahasiswa: boolean = true; let alamat: string | null = null; // union type // TypeScript bisa menyimpulkan tipe (type inference) let kota = "Jakarta"; // otomatis string let skor = 100; // otomatis number let aktif = true; // otomatis boolean // β Error: Type 'string' is not assignable to type 'number' // let angka: number = "ini bukan angka"; // Array let buah: string[] = ["apel", "mangga", "jeruk"]; let angka: Array<number> = [1, 2, 3, 4, 5]; // Tuple β array dengan tipe dan urutan tetap let mahasiswa: [string, number, boolean] = ["Budi", 25, true]; // Mengakses tuple console.log(mahasiswa[0]); // "Budi" console.log(mahasiswa[1]); // 25 // β Error: Type 'number' is not assignable to type 'string' // mahasiswa[0] = 123;
Union & Literal Types
// Union type β variabel bisa beberapa tipe
let id: string | number;
id = "ABC123"; // β
valid
id = 42; // β
valid
// id = true; // β error
// Literal type β nilai spesifik yang diizinkan
type Status = "aktif" | "nonaktif" | "pending";
let statusUser: Status = "aktif"; // β
valid
// statusUser = "deleted"; // β error
// Kombinasi literal + union
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
let method: HttpMethod = "GET";
// Nullable types
function cariUser(id: number): string | null {
if (id === 1) return "Budi";
return null; // User tidak ditemukan
}
let hasil = cariUser(1); // string | null
let tidakAda = cariUser(99); // null
Type untuk Object
// Object type inline
let pengguna: { nama: string; umur: number; email: string } = {
nama: "Budi",
umur: 25,
email: "budi@email.com"
};
// β Error: Property 'alamat' does not exist
// pengguna.alamat = "Jakarta";
// Optional property dengan ?
let produk: { nama: string; harga: number; diskon?: number } = {
nama: "Laptop",
harga: 15000000
// diskon tidak wajib
};
// Readonly property
let konfigurasi: { readonly apiUrl: string; timeout: number } = {
apiUrl: "https://api.example.com",
timeout: 5000
};
// β Error: Cannot assign to 'apiUrl' because it is read-only
// konfigurasi.apiUrl = "https://other.com";
4. Interfaces
Interface adalah cara untuk mendefinisikan bentuk (shape) dari sebuah object. Interface berfungsi sebagai kontrak yang harus dipenuhi oleh object.
Interface Dasar
// Mendefinisikan interface
interface Mahasiswa {
nama: string;
nim: string;
jurusan: string;
ipk: number;
aktif: boolean;
}
// Menggunakan interface
const mhs1: Mahasiswa = {
nama: "Budi Santoso",
nim: "2024001",
jurusan: "Teknik Informatika",
ipk: 3.85,
aktif: true
};
// β Error: Missing property 'jurusan'
// const mhs2: Mahasiswa = {
// nama: "Ani",
// nim: "2024002",
// ipk: 3.90,
// aktif: true
// };
// Optional & readonly properties
interface Produk {
readonly id: number;
nama: string;
harga: number;
deskripsi?: string; // opsional
stok: number;
}
const laptop: Produk = {
id: 1001,
nama: "Laptop Gaming",
harga: 15000000,
stok: 50
};
// β Error: Cannot assign to 'id' (readonly)
// laptop.id = 9999;
Interface untuk Function
// Interface untuk mendefinisikan bentuk fungsi
interface HitungFn {
(a: number, b: number): number;
}
const tambah: HitungFn = (a, b) => a + b;
const kali: HitungFn = (a, b) => a * b;
console.log(tambah(5, 3)); // 8
console.log(kali(5, 3)); // 15
// Interface dengan method
interface Kalkulator {
tambah(a: number, b: number): number;
kurang(a: number, b: number): number;
kali(a: number, b: number): number;
bagi(a: number, b: number): number;
}
const calc: Kalkulator = {
tambah: (a, b) => a + b,
kurang: (a, b) => a - b,
kali: (a, b) => a * b,
bagi: (a, b) => a / b
};
console.log(calc.tambah(10, 5)); // 15
console.log(calc.bagi(10, 3)); // 3.333...
Interface Inheritance
// Interface inheritance dengan extends
interface Kendaraan {
merek: string;
tahun: number;
warna: string;
}
interface Mobil extends Kendaraan {
jumlahPintu: number;
kapasitasMesin: number; // dalam cc
}
interface Motor extends Kendaraan {
jenisMotor: "matic" | "manual" | "sport";
}
const avanza: Mobil = {
merek: "Toyota",
tahun: 2024,
warna: "Putih",
jumlahPintu: 4,
kapasitasMesin: 1500
};
const vario: Motor = {
merek: "Honda",
tahun: 2024,
warna: "Hitam",
jenisMotor: "matic"
};
// Multiple inheritance
interface MobilSport extends Mobil {
turbo: boolean;
topSpeed: number;
}
const ferrari: MobilSport = {
merek: "Ferrari",
tahun: 2024,
warna: "Merah",
jumlahPintu: 2,
kapasitasMesin: 3900,
turbo: true,
topSpeed: 340
};
Gunakan interface untuk mendefinisikan bentuk object dan kontrak API. Jika Anda perlu union types atau mapped types, gunakan type alias. Keduanya bisa saling melengkapi!
5. Classes
TypeScript memperkaya class JavaScript dengan fitur seperti access modifiers, abstract classes, dan implements interface.
Class Dasar
// Class dasar dengan constructor
class Mahasiswa {
// Properties dengan access modifiers
public nama: string;
private nim: string;
protected jurusan: string;
readonly angkatan: number;
constructor(nama: string, nim: string, jurusan: string, angkatan: number) {
this.nama = nama;
this.nim = nim;
this.jurusan = jurusan;
this.angkatan = angkatan;
}
// Method
public getInfo(): string {
return `${this.nama} (${this.nim}) - ${this.jurusan}`;
}
// Private method
private validateNim(): boolean {
return this.nim.length === 8;
}
// Getter
get displayNama(): string {
return `Mahasiswa: ${this.nama}`;
}
}
const mhs = new Mahasiswa("Budi", "2024001", "TI", 2024);
console.log(mhs.nama); // β
Budi (public)
console.log(mhs.getInfo()); // β
Budi (2024001) - TI
console.log(mhs.displayNama); // β
Mahasiswa: Budi
// console.log(mhs.nim); // β Error: 'nim' is private
// console.log(mhs.jurusan); // β Error: 'jurusan' is protected
Shorthand Constructor
// Shorthand constructor β definisikan & assign sekaligus
class Produk {
constructor(
public nama: string,
public harga: number,
public kategori: string,
private _stok: number = 0
) {}
// Getter & Setter
get stok(): number {
return this._stok;
}
set stok(jumlah: number) {
if (jumlah < 0) {
throw new Error("Stok tidak boleh negatif!");
}
this._stok = jumlah;
}
getInfo(): string {
return `${this.nama} - Rp ${this.harga.toLocaleString()} (Stok: ${this._stok})`;
}
}
const laptop = new Produk("Laptop", 15000000, "Elektronik", 50);
console.log(laptop.getInfo());
// Laptop - Rp 15,000,000 (Stok: 50)
laptop.stok = 25; // β
menggunakan setter
// laptop.stok = -5; // β Error: Stok tidak boleh negatif!
Inheritance & Abstract Class
// Abstract class β tidak bisa diinstansiasi langsung
abstract class Hewan {
constructor(public nama: string, public kaki: number) {}
// Abstract method β HARUS diimplementasi di child
abstract suara(): string;
// Regular method β bisa diwariskan
getInfo(): string {
return `${this.nama} memiliki ${this.kaki} kaki`;
}
}
// β Error: Cannot create an instance of abstract class
// const hewan = new Hewan("Kucing", 4);
class Kucing extends Hewan {
constructor(nama: string) {
super(nama, 4); // panggil constructor parent
}
suara(): string {
return `${this.nama} bersuara: Meow! π±`;
}
}
class Anjing extends Hewan {
constructor(nama: string) {
super(nama, 4);
}
suara(): string {
return `${this.nama} bersuara: Guk guk! πΆ`;
}
}
const kucing = new Kucing("Kitty");
const anjing = new Anjing("Buddy");
console.log(kucing.suara()); // Kitty bersuara: Meow! π±
console.log(anjing.getInfo()); // Buddy memiliki 4 kaki
// Polymorphism
const hewanList: Hewan[] = [kucing, anjing];
hewanList.forEach(h => console.log(h.suara()));
Implements Interface
// Interface untuk kontrak
interface Printable {
print(): string;
}
interface Serializable {
serialize(): string;
deserialize(data: string): void;
}
// Class bisa implement beberapa interface
class Dokumen implements Printable, Serializable {
private isi: string = "";
constructor(public judul: string) {}
print(): string {
return `=== ${this.judul} ===\n${this.isi}`;
}
serialize(): string {
return JSON.stringify({ judul: this.judul, isi: this.isi });
}
deserialize(data: string): void {
const parsed = JSON.parse(data);
this.judul = parsed.judul;
this.isi = parsed.isi;
}
tambahIsi(teks: string): void {
this.isi += teks + "\n";
}
}
const doc = new Dokumen("Laporan Harian");
doc.tambahIsi("Hari ini belajar TypeScript.");
doc.tambahIsi("Sudah paham class dan interface.");
console.log(doc.print());
// === Laporan Harian ===
// Hari ini belajar TypeScript.
// Sudah paham class dan interface.
const serialized = doc.serialize();
console.log(serialized);
6. Modules
Modules memungkinkan Anda memecah kode menjadi file-file terpisah yang bisa saling mengimpor. TypeScript menggunakan sistem module ES6 (import/export).
Export & Import
// File: src/math.ts
// Named export
export function tambah(a: number, b: number): number {
return a + b;
}
export function kurang(a: number, b: number): number {
return a - b;
}
export const PI: number = 3.14159;
// Export interface
export interface OperasiMatematika {
hitung(a: number, b: number): number;
}
// Default export β satu per file
export default class Kalkulator implements OperasiMatematika {
hitung(a: number, b: number): number {
return a + b;
}
}
// File: src/app.ts
// Import named exports
import { tambah, kurang, PI } from "./math";
// Import default export
import Kalkulator from "./math";
// Import semua sebagai namespace
import * as MathUtils from "./math";
// Menggunakan imports
console.log(tambah(10, 5)); // 15
console.log(kurang(10, 5)); // 5
console.log(PI); // 3.14159
const calc = new Kalkulator();
console.log(calc.hitung(3, 7)); // 10
console.log(MathUtils.tambah(100, 200)); // 300
Re-export & Barrel Files
// File: src/models/User.ts
export interface User {
id: number;
nama: string;
email: string;
}
// File: src/models/Produk.ts
export interface Produk {
id: number;
nama: string;
harga: number;
}
// File: src/models/index.ts (Barrel file)
// Re-export semua dari models
export { User } from "./User";
export { Produk } from "./Produk";
// File: src/app.ts
// Import dari barrel file β lebih rapi!
import { User, Produk } from "./models";
const user: User = { id: 1, nama: "Budi", email: "budi@mail.com" };
const produk: Produk = { id: 1, nama: "Laptop", harga: 15000000 };
Pastikan module di tsconfig.json diatur ke "commonjs" (untuk Node.js) atau "ESNext" (untuk bundler seperti Webpack/Vite). Jangan lupa set "type": "module" di package.json jika menggunakan ES modules di Node.js.
7. Functions di TypeScript
TypeScript memungkinkan Anda mendefinisikan tipe untuk parameter dan return value fungsi secara eksplisit.
// Function dengan type annotations
function sapa(nama: string): string {
return `Halo, ${nama}!`;
}
// Arrow function dengan tipe
const kaliDua = (x: number): number => x * 2;
// Optional & default parameter
function buatProfil(
nama: string,
umur: number,
kota: string = "Jakarta", // default value
bio?: string // optional (bisa undefined)
): object {
return { nama, umur, kota, bio };
}
console.log(buatProfil("Budi", 25));
// { nama: "Budi", umur: 25, kota: "Jakarta", bio: undefined }
console.log(buatProfil("Sari", 22, "Bandung", "Hobi coding"));
// { nama: "Sari", umur: 22, kota: "Bandung", bio: "Hobi coding" }
// Rest parameters
function jumlahkan(...angka: number[]): number {
return angka.reduce((total, n) => total + n, 0);
}
console.log(jumlahkan(1, 2, 3)); // 6
console.log(jumlahkan(10, 20, 30, 40)); // 100
// Function overload
function format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase();
}
return `Rp ${value.toLocaleString()}`;
}
console.log(format("hello")); // "HELLO"
console.log(format(1500000)); // "Rp 1,500,000"
8. Enum
Enum (enumeration) adalah cara untuk mendefinisikan kumpulan nilai yang bernama. TypeScript mendukung numeric dan string enums.
// Numeric enum (default, dimulai dari 0)
enum Hari {
Minggu, // 0
Senin, // 1
Selasa, // 2
Rabu, // 3
Kamis, // 4
Jumat, // 5
Sabtu // 6
}
const hariIni: Hari = Hari.Rabu;
console.log(hariIni); // 3
console.log(Hari[3]); // "Rabu" (reverse mapping)
// String enum
enum StatusOrder {
Pending = "PENDING",
Diproses = "DIPROSES",
Dikirim = "DIKIRIM",
Selesai = "SELESAI",
Dibatalkan = "DIBATALKAN"
}
let status: StatusOrder = StatusOrder.Pending;
console.log(status); // "PENDING"
// Enum sebagai tipe parameter
function getStatusColor(status: StatusOrder): string {
switch (status) {
case StatusOrder.Pending: return "π‘ Kuning";
case StatusOrder.Diproses: return "π΅ Biru";
case StatusOrder.Dikirim: return "π Oranye";
case StatusOrder.Selesai: return "π’ Hijau";
case StatusOrder.Dibatalkan: return "π΄ Merah";
}
}
console.log(getStatusColor(StatusOrder.Selesai)); // π’ Hijau
// const enum β di-inline saat compile (lebih efisien)
const enum Role {
Admin = "ADMIN",
User = "USER",
Guest = "GUEST"
}
const role: Role = Role.Admin;
console.log(role); // "ADMIN"
9. Type Assertion & Casting
Type assertion memberitahu TypeScript bahwa Anda lebih tahu tipe data dari sebuah nilai. Gunakan dengan hati-hati!
// Type assertion dengan "as"
let nilai: unknown = "Hello TypeScript";
let panjang: number = (nilai as string).length;
console.log(panjang); // 15
// Type assertion dengan angle brackets (<>)
// Tidak bisa digunakan di JSX/TSX
let teks: unknown = "TypeScript";
let upper: string = (<string>teks).toUpperCase();
// Non-null assertion operator (!)
let elem: HTMLElement | null = document.getElementById("app");
// elem bisa null, tapi kita yakin elem ada
elem!.style.color = "red";
// Contoh aman β lebih disarankan
let elemAman = document.getElementById("app");
if (elemAman) {
elemAman.style.color = "blue"; // TypeScript tahu bukan null
}
// Type guard
function isString(value: unknown): value is string {
return typeof value === "string";
}
function proses(value: string | number): void {
if (isString(value)) {
console.log(`String: ${value.toUpperCase()}`);
} else {
console.log(`Number: ${value.toFixed(2)}`);
}
}
proses("hello"); // String: HELLO
proses(3.14159); // Number: 3.14
// keyof & typeof
interface Config {
apiUrl: string;
timeout: number;
retries: number;
}
type ConfigKey = keyof Config; // "apiUrl" | "timeout" | "retries"
function getConfig(config: Config, key: ConfigKey): string | number {
return config[key];
}
const config: Config = {
apiUrl: "https://api.example.com",
timeout: 5000,
retries: 3
};
console.log(getConfig(config, "apiUrl")); // β
console.log(getConfig(config, "timeout")); // β
// console.log(getConfig(config, "unknown")); // β Error
10. Quiz: Uji Pemahamanmu!
Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang TypeScript: